代码之家  ›  专栏  ›  技术社区  ›  Jitender

从数组中获取正确的索引值

  •  3
  • Jitender  · 技术社区  · 7 年前

    我必须以圆形的形式显示数组值,它必须永远在循环中运行。当你逆时针旋转的时候一切都很好。但当我们向相反的方向移动圆时,它有一个问题。

    我的轮子上有一个活动部件。因此,当用户单击任何其他幻灯片时,它会计算 单击 滑动和活动滑动,然后相应地添加和删除轮子中的项目。

    所以基本上它从数组中选择值。如果顺时针移动圆,它会从数组的后面拾取值;如果逆时针移动,它会从下一个可用的位置拾取值。如果在第一个页面加载中呈现了11个项,那么它将开始从12个无索引值中获取值。

    当您从活动元素中单击具有以上位置的项,然后再次逆时针旋转时,就会出现问题。

    假设您单击第8项,然后单击第7项。在这种情况下,应将2号部件添加到车轮中。

    这是 fiddle .

    var numberOfElement = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30];
    var initialRender = numberOfElement.slice(0, 11);
    var startPoint = initialRender.length;
    var endPoint = numberOfElement.length;
    
    function generateHtml() {
      var html = '';
      initialRender.forEach(function(item, index) {
        var angle = 18 * (index);
        var className = angle === 90 ? 'active' : '';
        html += '<div class="shapes ' + className + '" data-deg="' + angle + '" style="--deg:' + angle + 'deg;"> <span class="set-pos">' + (item) + '</span> <span> ' + angle + ' deg </span></div>';
      })
      document.querySelector('#dynamic-html').innerHTML = html;
    }
    
    generateHtml();
    
    $('#dynamic-html').on('click', '.shapes', function() {
      var deg = 90;
      var activeDeg = $('.active').data('deg');
      var needToremoveElement = activeDeg;
      var selectedElement = $(this).data('deg');
      var degrees = deg - selectedElement;
      var diff = Math.abs((activeDeg - selectedElement) / 18);
      $('.shapes').removeClass('active');
      $(this).addClass('active');
      var movementCloseWise = degrees > ($('.circle').data('deg') || 0);
      $('.circle').removeData('deg');
      $('.circle').css({
        'transform': 'rotate(' + degrees + 'deg)'
      }).attr('data-deg', degrees);
      if (movementCloseWise) {
        var itemLength = $('.shapes').length;
        $('.shapes:gt(' + ((itemLength - 1) - diff) + ')').remove()
    
        var newItems = generateItem(getItemsFromBack(diff), true);
        newItems = $(newItems).get().reverse();
        $('#dynamic-html').prepend(newItems)
        startPoint -= diff;
      } else {
        var newItems = generateItem(getItemFromStart(diff), false)
        $('#dynamic-html').append(newItems)
        $('.shapes:lt(' + (diff) + ')').remove()
        endPoint += diff;
      }
    
    })
    
    
    
    function getItemsFromBack(length) {
      var values = [];
      endPoint = endPoint - length;
      if (endPoint < 0) {
        endPoint = numberOfElement.length - Math.abs(endPoint)
        var otherVal = 0;
        if (endPoint + length >= numberOfElement.length) {
          otherVal = (endPoint + length) - numberOfElement.length;
          values = numberOfElement.slice(endPoint, numberOfElement.length)
        }
        if (otherVal > 0) {
          values = values.concat(numberOfElement.slice(0, otherVal))
        }
      } else {
        values = numberOfElement.slice(endPoint, endPoint + length)
      }
      var valuesCount = values.length;
      return values.reverse();
    }
    
    function getItemFromStart(length) {
      var values = numberOfElement.slice(startPoint, startPoint + length);
      var valueCount = values.length;
      startPoint += valueCount;
      if (valueCount < length) {
        startPoint = 0;
        return values.concat(getItemFromStart(length - valueCount));
      } else if (startPoint >= numberOfElement.length) {
        startPoint = 0;
      }
    
      return values;
    }
    
    function generateItem(items, isClockWise) {
      var html = "",
        lastItemAngle;
      if (isClockWise) {
        lastItemAngle = $('#dynamic-html .shapes:first').data('deg');
      } else {
        lastItemAngle = $('#dynamic-html .shapes:last').data('deg');
      }
    
      items.forEach(function(item, index) {
        if (isClockWise) {
          var angles = lastItemAngle - (18 * (index + 1))
        } else {
          var angles = lastItemAngle + (18 * (index + 1))
        }
        html += '<div class="shapes" data-deg="' + (angles) + '" style="--deg:' + angles + 'deg;"> <span class="set-pos">' + (item) + '</span> <span>   ' + angles + ' deg </span></div>';
      });
    
      return html;
    }
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   pouyan    7 年前

    我认为你的问题是 只是 你的 endPoint 初始化值。在代码中,将其初始化为 var endPoint = numberOfElement.length; 这是错误的(我认为),它应该由 0 ;我改变了它,它起了作用:

    var numberOfElement = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30];
        	var initialRender = numberOfElement.slice(0,11);
        	var startPoint = initialRender.length;
        	var endPoint = 0; /* here is the change */
        	function generateHtml(){
        		var html ='';
        		initialRender.forEach(function(item,index){
        			var angle = 18 * (index);
        			var className = angle === 90? 'active':'';
        			html+='<div class="shapes '+className+'" data-deg="'+angle+'" style="--deg:'+angle+'deg;"> <span class="set-pos">'+(item)+'</span> <span>	'+angle+' deg </span></div>';
        		})
        		document.querySelector('#dynamic-html').innerHTML= html;
        	}
    
    		generateHtml();
    		
        	$('#dynamic-html').on('click','.shapes',function(){
        		var deg = 90;
        		var activeDeg = $('.active').data('deg');
        		var needToremoveElement = activeDeg;
        		var selectedElement = $(this).data('deg');
        		var degrees = deg - selectedElement;
        		var diff = Math.abs((activeDeg - selectedElement) / 18);
        		$('.shapes').removeClass('active');
        		$(this).addClass('active');
        		var movementCloseWise = degrees > ($('.circle').data('deg') || 0);
        		$('.circle').removeData('deg');
        		$('.circle').css({'transform' : 'rotate('+ degrees +'deg)'}).attr('data-deg',degrees);
        		if(movementCloseWise){
        			var itemLength = $('.shapes').length;
        			$('.shapes:gt('+((itemLength-1)-diff)+')').remove()
    
        			var newItems = generateItem(getItemsFromBack(diff), true);
        			newItems =  $(newItems).get().reverse();
        			$('#dynamic-html').prepend(newItems)
        			startPoint -= diff;
        		}else{
        			var newItems = generateItem(getItemFromStart(diff), false)
        			$('#dynamic-html').append(newItems)
        			$('.shapes:lt('+(diff)+')').remove()
        			endPoint += diff;
        		}
        			
        	})
    
    
        	
    		function getItemsFromBack(length) {
    		   var values = [];
    		  endPoint = endPoint - length;
    		  if (endPoint < 0) {
    		    endPoint = numberOfElement.length - Math.abs(endPoint)
    		    var otherVal = 0;
    		    if (endPoint + length >= numberOfElement.length) {
    		      otherVal = (endPoint + length) - numberOfElement.length;
    		      values = numberOfElement.slice(endPoint, numberOfElement.length)
    		    }
    		    if (otherVal > 0) {
    		      values = values.concat(numberOfElement.slice(0, otherVal))
    		    }
    		  } else {
    		    values = numberOfElement.slice(endPoint, endPoint + length)
    		  }
    		  var valuesCount = values.length;
    		  return values.reverse();
    		}
    
        	function getItemFromStart(length) {
    		    var values = numberOfElement.slice(startPoint, startPoint + length);
    		    var valueCount = values.length;
        		startPoint += valueCount;
    		    if (valueCount < length) {
    		        startPoint = 0;
    		        return values.concat( getItemFromStart(length - valueCount) );
    		    } else if (startPoint >= numberOfElement.length) {
    		        startPoint = 0;
    		    }
    
    		    	return values;
    			}
    
    		function generateItem (items, isClockWise){
    			var html = "", lastItemAngle;	
    			if(isClockWise){
    				lastItemAngle = $('#dynamic-html .shapes:first').data('deg');	
    			}
    			else{
    			    lastItemAngle = $('#dynamic-html .shapes:last').data('deg');		
    			}
    			
    			items.forEach(function(item,index){
    				if(isClockWise){
    					var angles = lastItemAngle - (18 * (index +1))
    				}
    				else{
    					var angles = lastItemAngle + (18 * (index +1))	
    				}
        			html+='<div class="shapes" data-deg="'+(angles)+'" style="--deg:'+angles+'deg;"> <span class="set-pos">'+(item)+'</span> <span>	'+angles+' deg </span></div>';
        		});
    
        		return html;
    		}
    .main{
        	display: flex;
        	justify-content: center;
        	align-items: center;
        	height: 500px;
        }
        .pos{
    		height:150px;
    		width:150px;
    		position: relative;
        }
    	.circle{
    		background: red;
    		height:150px;
    		width:150px;
    		border-radius: 50%;
    		transition: transform 0.3s ease-in-out;
    	}
    	.shapes{
    		position: absolute;
    		top:calc(50% - 75px);
    		left:calc(50% - 10px);
    		width: 20px;
    	    height: 150px;
    	    transform: rotate(var(--deg)) translate(0, 160px); 
    	    background: green;
    	    text-align: center;
    	}
    
    	.fake-overlay{
        position: absolute;
        width: 203%;
        height: 320%;
        background: #fff;
        top: -160px;
        right: -148%;
        display: none
        
    	}
    	.active{
    		background: red
    	}
    	.set-pos{
    		position: absolute;
    		bottom: 0
    	}
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div class="main">
      		<div class="pos">
    	  		<div class="circle">
    	  			<div id="dynamic-html"></div>
    	  		</div>
    	  		<div class="fake-overlay"></div>
      		</div>
      	</div>

    这里是 Jsfiddle

        2
  •  1
  •   Jitender    7 年前

    我用以下代码修复了这个问题。

    function getItemsFromBack(length) {
      var values = [];
      if (endPoint > numberOfElement.length) {
        var diff = endPoint - numberOfElement.length;
        values = numberOfElement.slice(diff - length, diff)
        endPoint = endPoint - length;
        return values.reverse();
      }
      endPoint = endPoint - length;
      if (endPoint < 0) {
        endPoint = numberOfElement.length - Math.abs(endPoint)
        var otherVal = 0;
        if (endPoint + length >= numberOfElement.length) {
          otherVal = (endPoint + length) - numberOfElement.length;
          values = numberOfElement.slice(endPoint, numberOfElement.length)
        }
        if (otherVal > 0) {
          values = values.concat(numberOfElement.slice(0, otherVal))
        }
      } else {
        values = numberOfElement.slice(endPoint, endPoint + length)
      }
      var valuesCount = values.length;
      return values.reverse();
    }
    

    我正在检查端点是否大于数组的总长度。然后 endPoint- Array.length 并使用diff获取元素

        3
  •  1
  •   Tarun Lalwani    7 年前

    你的CSS很棒,但你的javascript仍然有缺陷。试试这个:

    单击7,然后单击2

    为了解决这个问题,我建议我们简化一下您的逻辑:

    • 为项目提供有意义的ID 所以我们可以很容易地选择它们,比较它们并推断出项目角度
    • 不要使用硬编码数组(如果是因为像jslint这样的代码质量工具,请考虑告诉它允许 for loops )

    代码的复杂性来自于对1-30范围内的起点和终点的管理。现在,通过上面的第一点,这变得容易了。

    我没有太多地更改您的代码,因此您可以轻松识别您的工作部件:

    // Global variables
    var numberOfItems = 30,
        numberOfRenderedItems = 11,
        firstItem = 0
    ;
    
    function generateHtml(){
        var html ='';
        for (var item = 0; item < numberOfRenderedItems; item++) {
            var angle = 18 * item,
                className = angle === 90? 'active':'';
            html +=
                '<div class="shapes '+className+'" data-item="'+item+'" data-deg="'+angle+'" style="--deg:'+angle+'deg;">'+
                ' <span class="set-pos">'+(item+1)+'</span>'+
                ' <span>'+angle+' deg </span>'+
                '</div>';
        }
        document.querySelector('#dynamic-html').innerHTML= html;
    }
    
    generateHtml();
    
    $('#dynamic-html').on('click','.shapes',function(){
    
        // Set clicked item active
        $('.shapes').removeClass('active');
        $(this).addClass('active');
    
        var selectedItem = Number($(this).data('item')),
            previousActiveItem = firstItem + Math.floor(numberOfRenderedItems/2),
            diff = selectedItem - previousActiveItem,
            selectedAngle = selectedItem * 18,
            degrees = 90 - selectedAngle,
            isClockWise = diff < 0;
    
        // Rotate all items
        $('.circle').removeData('deg');
        $('.circle').css({'transform' : 'rotate('+ degrees +'deg)'}).attr('data-deg',degrees);
    
        var items;
        if (isClockWise)
            items = getItemsFromBack(diff);
        else
            items = getItemsFromFront(diff);
    
        // Remove items
        items.toRemove.forEach( function (item) {
            $(".shapes[data-item="+item+"]").remove();        
        });
    
        // Add items
        var newItems = items.toAdd.reduce( function (html, item) {
            // Get item number between 1 and max
            var itemNumber = getNumberInRange(item),
                angle = 18 * item;
            return html +
                '<div class="shapes" data-item="'+item+'" data-deg="'+angle+'" style="--deg:'+angle+'deg;">'+
                ' <span class="set-pos">'+itemNumber+'</span>'+
                ' <span>'+angle+' deg </span>'+
                '</div>';
        }, '');
        if (isClockWise)
            $('#dynamic-html').append(newItems);
        else
            $('#dynamic-html').prepend(newItems)
    
    })
    
    function getItemsFromBack (diff) {
        var items = {
            toAdd: [],
            toRemove: []
        };
    
        firstItem += diff;
        for (var i = 0; i < Math.abs(diff); i++) {
            items.toAdd.push(firstItem + i);
            items.toRemove.push(firstItem + i + numberOfRenderedItems);
        }
    
        return items;
    }
    
    function getItemsFromFront (diff) {
        var items = {
            toAdd: [],
            toRemove: []
        };
    
        for (var i = 0; i < Math.abs(diff); i++) {
            items.toAdd.push(firstItem + i + numberOfRenderedItems);
            items.toRemove.push(firstItem + i);
        }
        firstItem += diff;
    
        return items;
    }
    
    function getNumberInRange (item) {
        do {
            item = (item + numberOfItems) % numberOfItems;
        }
        while (item < 0);
        return item + 1;
    }
    

    更新后的jsFiddle链接如下

    https://jsfiddle.net/dpvjtvjd/2/