2016-01-06 3 views
0

Я хочу создать ручку поиска игрока в круглой форме. У меня должно быть две ручки. один для буферизованной части (серый цвет на картинке), который не перетаскивается, а на другой элемент, который перетаскивается, и указывает текущую часть воспроизводимой песни. Я не уверен, как я могу это достичь. Кажется, что это лучший вариант. Но я не уверен, что элементы будут перетаскиваться в холст.Как создать круговую стрелочную полосу на холсте

var canvas = document.getElementById('myCanvas'); 
var context = canvas.getContext('2d'); 
var centerX = canvas.width/2; 
var centerY = canvas.height/2; 
var radius = 100; 

context.beginPath(); 
context.arc(centerX, centerY, radius, 0, 2 * Math.PI, false); 
context.lineWidth = 25; 
context.strokeStyle = '#003300'; 
context.stroke(); 

любая идея или пример, как ее достичь?

enter image description here

ответ

0

управления Круг

Этот ответ показать, как создать элемент управления типа игры. Он функционирует на фиксированном интервале и отображается один раз в каждом интервале. Он не управляется событиями, события мыши не вызывают управление, элемент управления просто проверяет текущую позицию мыши. Если интервал ниже интервала событий мыши, некоторые движения мыши будут потеряны, но контроль будет работать так же хорошо.

Этот элемент управления может быть легко адаптирован к событию, вызванному созданием собственных прослушивателей событий мыши и вызовом update и draw() при необходимости. Предупреждение, хотя этот элемент управления использует пользовательский объект мыши, чтобы изменить курсор и управлять тем, какой элемент управления имеет право собственности на мышь. Мышь нуждается в владении, так что, когда вы перетаскиваете один элемент управления над другим, вы не начинаете перетаскивать другой элемент управления. Он работает путем установки значения mouse.mousePrivate к элементам управления уникальному идентификатору элемента управления будет игнорировать мышь, если mouse.mousePrivate не равен 0 (без владельца) или идентификатора элемента управления

Смотрите код, как это работает. В демонстрации отображаются несколько элементов управления, показывающих различное поведение. Центральное управление - это простое управление диапазоном от 0 до 100, верхнее левое имеет 10 оборотов и диапазон от 0 до 1000 и показывает две позиции, чтобы показать позицию. Верхнее правое управление имеет плавающее значение, то есть если вы ищете видео, позиция поиска не отвечает сразу, поэтому у элемента управления есть плавающее значение, которое показывает дуги местоположения как фактическое положение, в то время как число и ручка набора показывают реальную позицию ,

Это просто пример, и вы должны просто взять то, что хотите. Он не тестировался более чем в нескольких браузерах, и не было ничего, кроме самого фундаментального тестирования, поэтому не используйте его как есть.

demo = function(){ 
 

 
    /** fullScreenCanvas.js begin **/ 
 
    var canvas = (function(){ 
 
     var canvas = document.getElementById("canv"); 
 
     if(canvas !== null){ 
 
      document.body.removeChild(canvas); 
 
     } 
 
     // creates a blank image with 2d context 
 
     canvas = document.createElement("canvas"); 
 
     canvas.id = "canv";  
 
     canvas.style.background = "#AAA"; 
 
     canvas.width = window.innerWidth; 
 
     canvas.height = window.innerHeight; 
 
     canvas.style.position = "absolute"; 
 
     canvas.style.top = "0px"; 
 
     canvas.style.left = "0px"; 
 
     canvas.style.zIndex = 1000; 
 
     canvas.ctx = canvas.getContext("2d"); 
 
     document.body.appendChild(canvas); 
 
     return canvas; 
 
    })(); 
 
    var ctx = canvas.ctx; 
 

 
    /** fullScreenCanvas.js end **/ 
 
    /** MouseFull.js begin **/ 
 

 
    var canvasMouseCallBack = undefined; // if needed 
 
    var mouse = (function(){ 
 
     function cursorControl(cursor){ 
 
      if(cursor !== this.lastCursor){ 
 
       if(cursor !== "default"){ 
 
        this.lastCursor = cursor; 
 
       } 
 
      } 
 
     } 
 
     function update(){ 
 
      if(this.element !== undefined){ 
 
       this.element.style.cursor = this.lastCursor; 
 
       this.lastCursor = "default"; 
 
      } 
 
     } 
 
     var mouse = { 
 
      x : 0, y : 0, w : 0, alt : false, shift : false, ctrl : false, 
 
      interfaceId : 1, buttonLastRaw : 0, buttonRaw : 0, 
 
      over : false, // mouse is over the element 
 
      bm : [1, 2, 4, 6, 5, 3], // masks for setting and clearing button raw bits; 
 
      getInterfaceId : function() { return this.interfaceId++; }, // For UI functions 
 
      mousePrivate : 0, 
 
      lastCursor: "default", 
 
      setCursor : cursorControl, 
 
      frameEnd : update, 
 
      startMouse:undefined, 
 
      element : undefined, 
 
     }; 
 
     function mouseMove(e) { 
 
      var t = e.type, m = mouse; 
 
      m.x = e.offsetX; m.y = e.offsetY; 
 
      if (m.x === undefined) { m.x = e.clientX; m.y = e.clientY; } 
 
      m.alt = e.altKey;m.shift = e.shiftKey;m.ctrl = e.ctrlKey; 
 
      if (t === "mousedown") { m.buttonRaw |= m.bm[e.which-1]; 
 
      } else if (t === "mouseup") { m.buttonRaw &= m.bm[e.which + 2]; 
 
      } else if (t === "mouseout") { m.buttonRaw = 0; m.over = false; 
 
      } else if (t === "mouseover") { m.over = true; 
 
      } else if (t === "mousewheel") { m.w = e.wheelDelta; 
 
      } else if (t === "DOMMouseScroll") { m.w = -e.detail;} 
 
      if (canvasMouseCallBack) { canvasMouseCallBack(m.x, m.y); } 
 
      e.preventDefault(); 
 
     } 
 
     function startMouse(element){ 
 
      if(element === undefined){ 
 
       element = document; 
 
      } 
 
      mouse.element = element; 
 
      "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",").forEach(
 
      function(n){element.addEventListener(n, mouseMove);}); 
 
      element.addEventListener("contextmenu", function (e) {e.preventDefault();}, false); 
 
     } 
 
     mouse.mouseStart = startMouse; 
 
     return mouse; 
 
    })(); 
 
    if(typeof canvas !== "undefined"){ 
 
     mouse.mouseStart(canvas); 
 
    }else{ 
 
     mouse.mouseStart(); 
 
    } 
 
    /** MouseFull.js end **/ 
 
    /** ImageTools.js begin **/ 
 
    var imageTools = (function(){ 
 
     var iT = { 
 
      canvas:function(w,h){var c=document.createElement("canvas");c.width=w;c.height=h;return c;}, 
 
      createImage:function(w,h){var i=iT.canvas(w,h);i.ctx=i.getContext("2d");return i;},   
 
      loadImage:function(url,cb){var i=new Image();i.src=url;i.addEventListener('load',cb);return i;}, 
 
      image2Canvas:function(ig){var i=iT.canvas(ig.width,ig.height);i.ctx=i.getContext("2d");i.drawImage(ig,0,0);return i;}, 
 
      imageData:function(img){return (img.ctx||(iT.image2Canvas(img).ctx)).getImageData(0,0,img.width,img.height).data;}, 
 
      saveAsPNG:function(image,filename){ // No IE <11 support. Chrome URL bug for large files may crash 
 
       var ac,e; 
 
       if(image.toDataURL === undefined){ image = it.image2Canvas(image);} 
 
       ac = document.createElement('a'); ac.href = image.toDataURL(); ac.download = filename+".png"; 
 
       // need to update this as it has depreciated. 
 
       if (document.createEvent) { 
 
        (e = document.createEvent("MouseEvents")).initMouseEvent("click", true, true, window,0, 0, 0, 0, 0, false, false, false,false, 0, null); 
 
        ac.dispatchEvent(e); 
 
       }  
 
      } 
 
     }; 
 
     return iT; 
 
    })(); 
 

 
    /** ImageTools.js end **/ 
 

 
    var w = canvas.width; 
 
    var h = canvas.height; 
 
    var ix = Math.ceil(Math.min(w, h)/20); 
 
    const PI2 = Math.PI * 2; 
 

 

 

 
    // following three function are for drawing, updating, and on to set floating value 
 

 
    // draw circular control needs to be bound to a circular control object 
 
    function drawCirControl(){ 
 
     var c, r, r1, r2, x, y, w, a; 
 
     c = this.ctx; 
 
     r = this.radius1; 
 
     r1 = this.radius2; 
 
     
 
     c.lineWidth = w = Math.abs(r - r1); 
 
     r2 = Math.min(r, r1) + w/2; 
 
     c.strokeStyle = this.borderColour; 
 
     c.beginPath(); 
 
     c.arc(this.x, this.y, r2, 0, Math.PI * 2) 
 
     c.stroke(); 
 
     c.strokeStyle = this.colour; 
 
     c.lineWidth = w - this.border * 2; 
 
     c.beginPath(); 
 
     c.arc(this.x, this.y, r2, 0, Math.PI * 2) 
 
     c.stroke(); 
 
     // if more than one turn between min and max then also display progress as one turn 
 
     if(Math.abs(this.startAng - this.endAng) > PI2){ 
 
      c.lineCap = "round"; 
 
      c.strokeStyle = this.lineColour; 
 
      c.lineWidth = (w - this.border * 6)/2; 
 
      c.beginPath(); 
 
      a = (this.floatingRaw - this.startAng) % PI2 + this.startAng; 
 
      c.arc(this.x, this.y, r2 + (w - this.border * 6)/4, this.startAng, a) 
 
      c.stroke(); 
 
      
 
      a = this.startAng + ((this.floatingValue - this.min)/(this.max - this.min)) * PI2; 
 
      c.lineCap = "round"; 
 
      c.strokeStyle = this.lineInnerColour; 
 
      c.lineWidth = (w - this.border * 6)/2; 
 
      c.beginPath(); 
 
      c.arc(this.x, this.y, r2 - (w - this.border * 6)/4, this.startAng, a) 
 
      c.stroke(); 
 
      
 
      
 
     }else{ 
 
      c.lineCap = "round"; 
 
      c.strokeStyle = this.lineColour; 
 
      c.lineWidth = w - this.border * 6; 
 
      c.beginPath(); 
 
      c.arc(this.x, this.y, r2, this.startAng, this.floatingRaw) 
 
      c.stroke(); 
 
     } 
 
     
 
     
 
     x = Math.cos(this.raw) * r2 + this.x; 
 
     y = Math.sin(this.raw) * r2 + this.y; 
 
     
 
     c.lineWidth = this.border; 
 
     c.strokeStyle = this.borderColour; 
 
     c.fillStyle = this.colour; 
 
     c.beginPath(); 
 
     c.arc(x, y, (w * this.handleSize)/2, 0, Math.PI * 2); 
 
     c.fill(); 
 
     c.stroke(); 
 
     
 
     c.font = this.font; 
 
     c.textAlign = "center"; 
 
     c.textBaseline = "middle"; 
 
     c.fillText(Math.round(this.value), this.x, this.y); 
 
    } 
 

 
    // Update by checking mouse position and setting cursor and controling the dragging 
 
    // circular control needs to be bound to a circular control object 
 
    function updateCircularControl(){ 
 
     var r, r1, r2, x, y, dist, ang, a, w, h, mouseOver; 
 
     r = this.radius1; 
 
     r1 = this.radius2; 
 
     w = Math.abs(r - r1); 
 
     r2 = Math.min(r, r1) + w/2; 
 
     if(!this.floating){ 
 
      this.floatingValue = this.value; 
 
     } 
 
     this.raw = (this.value/(this.max - this.min)) * (this.endAng - this.startAng) + this.startAng; 
 
     this.floatingRaw = (this.floatingValue/(this.max - this.min)) * (this.endAng - this.startAng) + this.startAng; 
 
     x = Math.cos(this.raw) * r2 + this.x; 
 
     y = Math.sin(this.raw) * r2 + this.y; 
 
     mouseOver = false; 
 
     dist = Math.sqrt(Math.pow(x - mouse.x, 2) + Math.pow(y - mouse.y, 2)); 
 
     if(this.mouse.mousePrivate === 0 || this.mouse.mousePrivate === this.id){ 
 
      if(dist < w * this.handleSize || this.dragging){ 
 
       this.mouse.setCursor("pointer"); 
 
       mouseOver = true; 
 
       this.mouse.mousePrivate = this.id; 
 
       if((this.mouse.buttonRaw & 1) === 1 && !this.dragging){ 
 
        this.dragging = true; 
 
         this.lastAng = (this.raw + PI2) % PI2; 
 
        
 
       }else{ 
 
        if((this.mouse.buttonRaw & 1) === 0){ 
 
         this.dragging = false; 
 
        }else{ 
 
         // get the angle to the mouse 
 
         ang = ((Math.atan2(mouse.y - this.y, mouse.x - this.x)) + PI2) % PI2; 
 
         // get the delta from last angle 
 
         a = (ang - this.lastAng); 
 
         // check that is has not cycled and adjust acordingly 
 
         if(a < -Math.PI * (3/2)){ 
 
          a += PI2 
 
         } 
 
         if(a > Math.PI * (3/2)){ 
 
          a -= PI2 
 
         } 
 
         // set last angle 
 
         this.lastAng = ang; 
 
         // set the raw vale 
 
         this.raw += a; 
 
         this.value = ((this.raw - this.startAng)/(this.endAng - this.startAng)) * (this.max - this.min) + this.min 
 
         this.value = Math.min(this.max, Math.max(this.min, this.value)); 
 
         if(!this.floating){ 
 
          this.floatingValue = this.value; 
 
         } 
 
         // recalculate the raw value 
 
         this.raw = (this.value/(this.max - this.min)) * (this.endAng - this.startAng) + this.startAng; 
 
         this.floatingRaw = (this.floatingValue/(this.max - this.min)) * (this.endAng - this.startAng) + this.startAng; 
 
        } 
 
       } 
 
      } 
 
     } 
 
     if(! mouseOver && this.mouse.mousePrivate === this.id){ 
 
      this.mouse.mousePrivate = 0; 
 
     } 
 
    } 
 
    // set circular control floating value needs to be bound to a circular control object 
 

 
    function setCirciularFloatingValue(v){ 
 
     this.floatingValue = v; 
 
     this.floatingRaw = (this.floatingValue/(this.max - this.min)) * (this.endAng - this.startAng) + this.startAng; 
 
    } 
 

 

 

 
    // create a circular control 
 
    // x, y is the center pos; 
 
    // min max is the min max values 
 
    // r1 r2 are inner and outer radius 
 
    // ctx is the canvas context to draw to 
 
    // mouse is the mouse object. This is a custom mouse object provided 
 
    //  in the demo. 
 

 
    function createCircularControl(x,y,min,max,r1,r2,ctx,mouse){ 
 
     var s, fontSize; 
 
     s = Math.min(r1,r2); 
 
     fontSize = Math.ceil(s/2);    
 
     var control = { 
 
      raw : 0,     // the raw angle to draw the control handle ar 
 
      floatingRaw : 0,   // if the actuale value floats independent of control position 
 
      lastAng : 0, 
 
      x : x,      // center of control 
 
      y : y, 
 
      min : min,     // min and max values 
 
      max : max, 
 
      value : 0,     // value of control 
 
      floatingValue : 0, 
 
      startAng : -Math.PI/2,  // start angle 
 
      endAng : Math.PI * (3/2), // end angle 
 
      radius1 : r1,    // inner and outer angles 
 
      radius2 : r2, 
 
      border : 1,     // border radius 
 
      colour : "white",   // inner colour 
 
      borderColour : "black",  // border colour 
 
      lineColour : "#5AF", 
 
      lineInnerColour : "#5AF", 
 
      font : fontSize + "px Arial Black", // font for center display 
 
      handleSize : 1.5,   // handle size aas ratio to control width 
 
      floating : false, 
 
      draw : drawCirControl,  // function to draw control 
 
      ctx : ctx,     // get the context to draw to 
 
      mouse : mouse,    // set the mouse 
 
      id : mouse.getInterfaceId(), // get an ID for this control 
 
      update : updateCircularControl, // updates the control 
 
      setFloatingValue : setCirciularFloatingValue, 
 
     } 
 
     return control; 
 
    } 
 

 

 
    // create the controls 
 
    var cont = createCircularControl(w/2, h/2, 0, 100, ix*5, ix*6, ctx, mouse); 
 
    var cont1 = createCircularControl(w/6, h/4, 0, 1000, ix*2, ix*3, ctx, mouse); 
 
    var cont2 = createCircularControl(w - w/6, h/4, 0, 1000, ix*2, ix*3, ctx, mouse); 
 

 
    // set up top left control extra attributes 
 
    // It has 10 rotations between min and max 
 
    cont1.startAng = -Math.PI/2; 
 
    cont1.endAng = -Math.PI/2 + PI2 * 10; 
 
    cont1.handleSize = 1.0; 
 
    cont1.lineInnerColour = "#8C5"; 
 

 

 
    // set up top left control extra attributes 
 
    cont2.startAng = 0; 
 
    cont2.endAng = PI2 * 5; 
 
    cont2.handleSize = 1.5; 
 
    cont2.lineInnerColour = "#C85"; 
 
    cont2.colour = "black"; 
 
    cont2.borderColour = "Green"; 
 
    cont2.border = 3; 
 
    cont2.floating = true; 
 
    var fValue = 0; 
 
    var fdValue = 0 
 

 

 

 
    // Updates all 
 
    function update(){ 
 
     ctx.setTransform(1,0,0,1,0,0); 
 
     ctx.clearRect(0, 0, w, h); 
 
     fdValue += (cont2.value - fValue) * 0.01; 
 
     fdValue *= 0.6; 
 
     fValue += fdValue; 
 
     cont2.setFloatingValue(fValue); 
 
     cont.update(); 
 
     cont1.update(); 
 
     cont2.update(); 
 
     cont.draw(); 
 
     cont1.draw(); 
 
     cont2.draw(); 
 
     if(!STOP){ 
 
      requestAnimationFrame(update); 
 
     }else{ 
 
      var canv = document.getElementById("canv"); 
 
      if(canv !== null){ 
 
       document.body.removeChild(canv); 
 
      }    
 
      STOP = false; 
 
     } 
 
     mouse.frameEnd(); 
 
     
 
    } 
 

 
    update(); 
 
    
 
} 
 
var STOP = false; 
 
function resizeEvent(){ 
 
    var waitForStopped = function(){ 
 
     if(!STOP){ // wait for stop to return to false 
 
      demo(); 
 
      return; 
 
     } 
 
     setTimeout(waitForStopped,200); 
 
    } 
 
    STOP = true; 
 
    setTimeout(waitForStopped,100); 
 
} 
 
window.addEventListener("resize",resizeEvent); 
 
demo();

Смежные вопросы