2016-07-11 13 views
5

मैं एक अच्छा ड्रैग लागू करने और 3 डिस्क का प्रतिनिधित्व करने वाले कैनवास पर ड्रॉप करने का प्रयास करता हूं।नाइस खींचें और कैनवास पर ड्रॉप करें HTML5

मैं माउस के साथ प्रत्येक द्रव्यमान की स्थिति बदलना चाहता हूं। मेरी मुख्य समस्या यह है कि मैं इन तीन क्षेत्रों में से प्रत्येक के लिए कुल्हाड़ी की लंबाई से बाध्य हूं।

पल के लिए, मैं निम्नलिखित समारोह जब माउस कैनवास के अंदर चल रहा है को लागू किया है (indexMass का मूल्य जो बड़े पैमाने पर ले जाया जाता है इंगित करता है: 1, 2 or 3 और t1, t2, t3 क्रमशः का प्रतिनिधित्व करता है the angle of mass 1, 2, 3):

// Happens when the mouse is moving inside the canvas 
function myMove(event) { 

    if (isDrag) { 
    var x = event.offsetX; 
    var y = event.offsetY; 

    if (indexMass == 1) 
     { // Update theta1 value 
     t1 = t1 + 0.1*Math.atan(y/x); 
     } 
    else if (indexMass == 2) 
     { // Update theta2 value 
     t2 = t2 + 0.1*Math.atan(y/x); 
     } 
    else if (indexMass == 3) 
     { // Update theta3 value 
     t3 = t3 + 0.1*Math.atan(y/x); 
     } 

    // Update drawing 
    DrawPend(canvas); 

    }  

} 

आप देख सकते हैं

t = t + 0.1*Math.atan(y/x); 

साथ:

var x = event.offsetX; 
var y = event.offsetY; 
, मैं प्रत्येक कोण के लिए किया था

लेकिन यह प्रभाव बहुत अच्छा नहीं है। एक बार गोलाकार माउस (माउस क्लिक पर) के साथ चुने जाने के बाद, मैं कर्सर को इस क्षेत्र या क्षेत्र के साथ फंसे होने के लिए माउस निर्देशांक के "delta" का पालन करने के लिए पसंद करूंगा जब मैं अब क्षेत्र में नहीं हूं।

संक्षेप में, मुझे नहीं पता कि कैसे एक अच्छा और उपयोगकर्ता के अनुकूल ड्रैग और ड्रॉप बनाने के लिए, अगर कोई मेरी मदद कर सकता है या मुझे कुछ सलाह दे सकता है, तो यह बहुत अच्छा होगा।

धन्यवाद

UPDATE 1

@ Blindman67: आपकी मदद के लिए धन्यवाद, आपका कोड स्निपेट, मैं यह सब समझ में नहीं आया मेरे लिए बहुत जटिल है। लेकिन मैं सही रास्ते पर हूं।

मैं पहली समस्या से शुरू कर रहा हूं: खींचने पर माउस को चयनित डिस्क को घुमाएं या उस पर बहुत अधिक बंद कर दें।

पल के लिए, मैं की तरह मेरे समारोह myMove (जो जब मैं नीचे क्लिक किया और खींच के लिए माउस को स्थानांतरित कर दिया है कहा जाता है) को संशोधित किया है:

// Happens when the mouse is moving inside the canvas 
function myMove(event) { 

    // If dragging 
    if (isDrag) { 

    // Compute dx and dy before calling DrawPend 
    var lastX = parseInt(event.offsetX - mx); 
    var lastY = parseInt(event.offsetY - my); 

    var dx = lastX - window['x'+indexMass]; 
    var dy = lastY - window['y'+indexMass]; 

    // Change angle when dragging 
    window['t'+indexMass] = Math.atan2(dy, dx); 

    // Update drawing 
    DrawPend(canvas); 

    // Highlight dragging disk 
    fillDisk(indexMass, 'pink'); 

    }      

} 

जहां indexMass घसीटा डिस्क और window['x'+indexMass] का सूचकांक है, window['y'+indexMass] चयनित डिस्क केंद्र के वर्तमान निर्देशांक हैं।

के बाद, मैं dx, dy क्रमशः निर्देशांक माउस से क्लिक किया गणना जब खींचें (mx, mygetMousePos function द्वारा दिया) शुरू करने और माउस को ले के साथ समन्वय।

अंत में, मैं सेट द्वारा डिस्क के कोण बदलने के लिए, वैश्विक चर (चयनित डिस्क की थीटा), यानी window['t'+indexMass] के लिए:

// Change angle when dragging 
window['t'+indexMass] = Math.atan2(dy, dx); 

मैं Math.atan2 साथ कोड के अपने भाग लिया है।

लेकिन इस फ़ंक्शन का परिणाम माउस ड्रैगिंग के साथ एक अच्छी एनीमेशन नहीं बनाता है, मैं जानना चाहता हूं कि यह कहां से आ सकता है।

अभी, मैं अक्ष की लंबाई को संशोधित किए बिना केवल ड्रैगिंग को लागू करना चाहता हूं, मैं इस कार्यक्षमता के लिए और बाद में देखूंगा।

अद्यतन 2

मैं माउस के साथ एक चयनित द्रव्यमान का खींचने के बारे में समाधान खोजने के लिए चल रहा है रहते हैं।

मैं पहले क्या किया है का एक संश्लेषण की कोशिश कर के लिए, मेरा मानना ​​है कि निम्नलिखित विधि अच्छा है, लेकिन यह खींच विधि बहुत अच्छी तरह से काम नहीं कर रहा: चयनित डिस्क सही ढंग से माउस का पालन नहीं करता और मैं नहीं जानता कि क्यूं कर।

  1. कंप्यूट dx, माउस निर्देशांक और चयनित डिस्क निर्देशांक, यानी के बीच डीवाई:

वर dx

myMove function में (समारोह कहा जाता है जब मैं खींचना शुरू करें), मैं करने का निर्णय लिया = parseInt (event.offsetX - विंडो ['x' + indexMass]);

var dy = parseInt (event.offsetY - विंडो ['y' + indexMass]);

indexMass चयनित डिस्क के सूचकांक का प्रतिनिधित्व करता है।

  1. वृद्धि चयनित डिस्क की स्थिति dx, dy द्वारा (अस्थायी चर tmpX, tmpY में संग्रहीत)।

  2. कंप्यूट नया कोण theta (वैश्विक चर window['t'+indexMass]

  3. कंप्यूट नई यानी disk1 (indexMass=1 और थीटा = t1) के साथ उदाहरण के लिए theta के इस नए मूल्य के साथ चयनित डिस्क की स्थिति, द्वारा कोड में पहचान:

    x1= x0 +l1 * sin(t1) 
    y1= y0 +l1 * sin(t1) 
    

मैं आपको लगता है कि मैं माउस के साथ खींचकर चाहते की लंबाई को संशोधित करने के लिए नहीं बनाने के लिए माउस के साथ अक्ष, यह एक बाधा है।

यहाँ पूरे myMove function (कहा जाता है जब खींचें शुरू कर रहा है) है:

// Happens when the mouse is moving inside the canvas 
function myMove(event) { 

    // If dragging 
    if (isDrag) { 

    console.log('offsetX', event.offsetX); 
    console.log('offsetY', event.offsetY); 
    var dx = parseInt(event.offsetX - window['x'+indexMass]); 
    var dy = parseInt(event.offsetY - window['y'+indexMass]); 
    console.log('dx', dx); 
    console.log('dy', dy); 

     // Temp variables 
     var tmpX = window['x'+indexMass]; 
     var tmpY = window['y'+indexMass]; 

     // Increment temp positions 
     tmpX += dx; 
     tmpY += dy; 
     // Compute new angle for indexMass 
     window['t'+indexMass] = Math.atan2(tmpX, tmpY); 
     console.log('printf', window['t'+indexMass]); 

     // Compute new positions of disks 
     dragComputePositions(); 

     // Update drawing 
     DrawPend(canvas); 

     // Highlight dragging disk 
     fillDisk(indexMass, 'pink'); 

    } 
} 

अद्यतन 4 - बाउंटी:

समस्या हल! मैं Math.atan2 फ़ंक्शन के साथ नए कोण की गणना करने के लिए "indexMass-1" डिस्क की स्थिति को ध्यान में रखना भूल गया।

उत्तर

5

आप ओएस माउस स्थिति को स्थानांतरित नहीं कर सकते हैं। आप माउस canvas.style.cursor = "none"; को छुपा सकते हैं और फिर अपने स्वयं के कैनवास पर माउस खींच सकते हैं, लेकिन यह एक फ्रेम से पीछे हट जाएगा क्योंकि जब आप माउस को निर्देशित करते हैं तो ओएस पहले ही उस स्थिति में माउस रख चुका है, और यदि आप अनुरोध का उपयोग करते हैंएनिमेशन फ्रेम (आरएएफ) कैनवास की अगली प्रस्तुति अगले डिस्प्ले रीफ्रेश अंतराल पर होगी। यदि आप आरएएफ का उपयोग नहीं करते हैं तो आप वर्तमान डिस्प्ले रीफ्रेश पर कैनवास पेश कर सकते हैं या नहीं कर सकते हैं, लेकिन आपको कभी-कभार झिलमिलाहट और कतरनी मिल जाएगी।

समस्या को हल करने के लिए (जो व्यक्तिपरक है) गेंद के माध्यम से गेंद के माध्यम से घूर्णन बिंदु से एक रेखा खींचती है, यह कम से कम उपयोगकर्ता को कुछ प्रतिक्रिया दे रही है कि क्या हो रहा है।

मैं गेंदों में कुछ हैंडल भी जोड़ूंगा ताकि आप द्रव्यमान (गोलाकार * घनत्व की मात्रा) और धुरी की लंबाई बदल सकें .. आकार बदलने वाले कर्सर एक समस्या है क्योंकि आवश्यक आंदोलन की दिशा से मेल नहीं खाएगा कोणों में परिवर्तन हैं। आपको सही कोण के सबसे नज़दीक को ढूंढना होगा या कर्सर को कैनवास में प्रस्तुत करना होगा और इसका उपयोग करना होगा।

उदाहरण कोड दिखाता है कि मेरा क्या मतलब है। , गेंदों पर माउस ले जाएँ ले जाने के लिए (सिम शामिल नहीं है) जब से अधिक आप भी दो हलकों दूरी और त्रिज्या (मास)

/*------------------------------------------------------------------------------------- 
 
answer code 
 
---------------------------------------------------------------------------------------*/ 
 

 

 

 

 

 

 
var balls = []; 
 
var startX,startY; 
 
var mouseOverBallIndex = -1; 
 
var mouseOverDist = false; 
 
var mouseOverMass = false; 
 
const DRAG_CURSOR = "move"; 
 
const MASS_CURSOR = "ew-resize"; 
 
const DIST_CURSOR = "ns-resize"; 
 
var dragging = false; 
 
var dragStartX = 0; 
 
var dragStartY = 0; 
 
function addBall(dist,radius){ 
 
    balls.push({ 
 
     dist : dist, 
 
     radius : Math.max(10,radius), 
 
     angle : -Math.PI/2, 
 
     x : 0, 
 
     y : 0, 
 
     mass : (4/3) * radius * radius * radius * Math.PI, 
 
    }); 
 
} 
 
function drawBalls(){ 
 
    var i = 0; 
 
    var len = balls.length; 
 
    var x,y,dist,b,minDist,index,cursor; 
 
    ctx.lineWidth = 2; 
 
    ctx.strokeStyle = "black"; 
 
    ctx.fillStyle = "blue" 
 
    ctx.beginPath(); 
 
    x = startX; 
 
    y = startY; 
 
    ctx.moveTo(x, y) 
 
    for(; i < len; i += 1){ 
 
     b = balls[i]; 
 
     x += Math.cos(b.angle) * b.dist; 
 
     y += Math.sin(b.angle) * b.dist; 
 
     ctx.lineTo(x, y); 
 
     b.x = x; 
 
     b.y = y; 
 
    } 
 
    ctx.stroke(); 
 
    minDist = Infinity; 
 
    index = -1; 
 
    for(i = 0; i < len; i += 1){ 
 
     b = balls[i]; 
 
     ctx.beginPath(); 
 
     ctx.arc(b.x, b.y, b.radius, 0, Math.PI * 2); 
 
     ctx.fill(); 
 
     if(!dragging){ 
 
      x = b.x - mouse.x; 
 
      y = b.y - mouse.y; 
 
      dist = Math.sqrt(x * x + y * y); 
 
      if(dist < b.radius + 5 && dist < minDist){ 
 
       minDist = dist; 
 
       index = i; 
 
      } 
 
     } 
 
    } 
 
    if(!dragging){ 
 
     mouseOverBallIndex = index; 
 
     if(index !== -1){ 
 
      cursor = DRAG_CURSOR; 
 
      b = balls[index]; 
 
      ctx.fillStyle = "Red" 
 
      ctx.beginPath(); 
 
      ctx.arc(b.x, b.y, b.radius, 0, Math.PI * 2); 
 
      ctx.fill(); 
 
      dx = b.x - Math.cos(b.angle) * b.radius; 
 
      dy = b.y - Math.sin(b.angle) * b.radius; 
 
      x = dx - mouse.x; 
 
      y = dy - mouse.y; 
 
      dist = Math.sqrt(x * x + y * y); 
 
      ctx.beginPath(); 
 
      if(dist < 6){ 
 
       ctx.strokeStyle = "Yellow" 
 
       mouseOverDist = true; 
 
       ctx.arc(dx, dy, 12, 0, Math.PI * 2); 
 
       cursor = DIST_CURSOR; 
 
      }else{ 
 
       ctx.strokeStyle = "black" 
 
       mouseOverDist = false; 
 
       ctx.arc(dx, dy, 5, 0, Math.PI * 2); 
 

 
      } 
 
      ctx.stroke();MASS_CURSOR 
 
      dx = b.x - Math.cos(b.angle + Math.PI/2) * b.radius; 
 
      dy = b.y - Math.sin(b.angle + Math.PI/2) * b.radius; 
 
      x = dx - mouse.x; 
 
      y = dy - mouse.y; 
 
      dist = Math.sqrt(x * x + y * y); 
 
      ctx.beginPath(); 
 
      if(dist < 6){ 
 
       ctx.strokeStyle = "Yellow" 
 
       mouseOverMass = true; 
 
       ctx.arc(dx, dy, 12, 0, Math.PI * 2); 
 
       cursor = MASS_CURSOR; 
 
      }else{ 
 
       ctx.strokeStyle = "black" 
 
       mouseOverMass = false; 
 
       ctx.arc(dx, dy, 5, 0, Math.PI * 2); 
 

 
      } 
 
      ctx.stroke(); 
 
      canvas.style.cursor = cursor; 
 
     }else{ 
 
      canvas.style.cursor = "default"; 
 
     } 
 
    }else{ 
 
     b = balls[mouseOverBallIndex]; 
 
     ctx.fillStyle = "Yellow" 
 
     ctx.beginPath(); 
 
     ctx.arc(b.x, b.y, b.radius, 0, Math.PI * 2); 
 
     ctx.fill();   
 
     
 
    } 
 

 
} 
 
function display(){ // put code in here 
 
    var x,y,b 
 
    
 
    if(balls.length === 0){ 
 
     startX = canvas.width/2; 
 
     startY = canvas.height/2; 
 
     addBall((startY * 0.8) * (1/4), startY * 0.04); 
 
     addBall((startY * 0.8) * (1/3), startY * 0.04); 
 
     addBall((startY * 0.8) * (1/2), startY * 0.04); 
 
     
 
    } 
 
    ctx.setTransform(1,0,0,1,0,0); // reset transform 
 
    ctx.globalAlpha = 1;   // reset alpha 
 
    ctx.clearRect(0,0,w,h); 
 
    if((mouse.buttonRaw & 1) && mouseOverBallIndex > -1){ 
 
     b = balls[mouseOverBallIndex]; 
 
     if(dragging === false){ 
 
      dragging = true; 
 
      dragStartX = balls[mouseOverBallIndex].x; 
 
      dragStartY = balls[mouseOverBallIndex].y; 
 
     }else{ 
 
      b = balls[mouseOverBallIndex]; 
 
      if(mouseOverBallIndex === 0){ 
 
       x = startX; 
 
       y = startY; 
 
      }else{ 
 
       x = balls[mouseOverBallIndex-1].x 
 
       y = balls[mouseOverBallIndex-1].y 
 
      } 
 
      if(mouseOverDist){ 
 
       var dist = Math.sqrt(Math.pow(x-mouse.x,2)+Math.pow(y-mouse.y,2)); 
 
       b.dist = dist + b.radius; 
 
       
 
      }else  
 
      if(mouseOverMass){ 
 
       var dist = Math.sqrt(Math.pow(dragStartX-mouse.x,2)+Math.pow(dragStartY-mouse.y,2)); 
 
       b.radius = Math.max(10,dist); 
 
       b.mass = dist * dist * dist * (4/3) * Math.PI; 
 
      }else{ 
 
       b.angle = Math.atan2(mouse.y - y, mouse.x - x); 
 
       ctx.beginPath(); 
 
       ctx.lineWidth = 1; 
 
       ctx.strokeStyle = "grey"; 
 
       ctx.moveTo(x,y); 
 
       ctx.lineTo(mouse.x, mouse.y); 
 
       ctx.stroke(); 
 
      } 
 
     } 
 
     
 
    }else if(dragging){ 
 
     dragging = false; 
 
    } 
 

 
    drawBalls(); 
 
} 
 

 
/*------------------------------------------------------------------------------------- 
 
answer code END 
 
---------------------------------------------------------------------------------------*/ 
 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 
/** SimpleFullCanvasMouse.js begin **/ 
 
const CANVAS_ELEMENT_ID = "canv"; 
 
const U = undefined; 
 
var w, h, cw, ch; // short cut vars 
 
var canvas, ctx, mouse; 
 
var globalTime = 0; 
 
var createCanvas, resizeCanvas, setGlobals; 
 
var L = typeof log === "function" ? log : function(d){ console.log(d); } 
 
createCanvas = function() { 
 
    var c,cs; 
 
    cs = (c = document.createElement("canvas")).style; 
 
    c.id = CANVAS_ELEMENT_ID;  
 
    cs.position = "absolute"; 
 
    cs.top = cs.left = "0px"; 
 
    cs.zIndex = 1000; 
 
    document.body.appendChild(c); 
 
    return c; 
 
} 
 
resizeCanvas = function() { 
 
    if (canvas === U) { canvas = createCanvas(); } 
 
    canvas.width = window.innerWidth; 
 
    canvas.height = window.innerHeight; 
 
    ctx = canvas.getContext("2d"); 
 
    if (typeof setGlobals === "function") { setGlobals(); } 
 
} 
 
setGlobals = function(){ cw = (w = canvas.width)/2; ch = (h = canvas.height)/2; balls.length = 0; } 
 
mouse = (function(){ 
 
    function preventDefault(e) { e.preventDefault(); } 
 
    var mouse = { 
 
     x : 0, y : 0, w : 0, alt : false, shift : false, ctrl : false, buttonRaw : 0, 
 
     over : false, // mouse is over the element 
 
     bm : [1, 2, 4, 6, 5, 3], // masks for setting and clearing button raw bits; 
 
     mouseEvents : "mousemove,mousedown,mouseup,mouseout,mouseover,mousewheel,DOMMouseScroll".split(",") 
 
    }; 
 
    var m = mouse; 
 
    function mouseMove(e) { 
 
     var t = e.type; 
 
     m.x = e.offsetX; m.y = e.offsetY; 
 
     if (m.x === U) { 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 (m.callbacks) { m.callbacks.forEach(c => c(e)); } 
 
     e.preventDefault(); 
 
    } 
 
    m.addCallback = function (callback) { 
 
     if (typeof callback === "function") { 
 
      if (m.callbacks === U) { m.callbacks = [callback]; } 
 
      else { m.callbacks.push(callback); } 
 
     } else { throw new TypeError("mouse.addCallback argument must be a function"); } 
 
    } 
 
    m.start = function (element, blockContextMenu) { 
 
     if (m.element !== U) { m.removeMouse(); }   
 
     m.element = element === U ? document : element; 
 
     m.blockContextMenu = blockContextMenu === U ? false : blockContextMenu; 
 
     m.mouseEvents.forEach(n => { m.element.addEventListener(n, mouseMove); }); 
 
     if (m.blockContextMenu === true) { m.element.addEventListener("contextmenu", preventDefault, false); } 
 
    } 
 
    m.remove = function() { 
 
     if (m.element !== U) { 
 
      m.mouseEvents.forEach(n => { m.element.removeEventListener(n, mouseMove); }); 
 
      if (m.contextMenuBlocked === true) { m.element.removeEventListener("contextmenu", preventDefault);} 
 
      m.element = m.callbacks = m.contextMenuBlocked = U; 
 
     } 
 
    } 
 
    return mouse; 
 
})(); 
 
var done = function(){ 
 
    window.removeEventListener("resize",resizeCanvas) 
 
    mouse.remove(); 
 
    document.body.removeChild(canvas);  
 
    canvas = ctx = mouse = U; 
 
    L("All done!") 
 
} 
 

 
resizeCanvas(); // create and size canvas 
 
mouse.start(canvas,true); // start mouse on canvas and block context menu 
 
window.addEventListener("resize",resizeCanvas); // add resize event 
 

 
function update(timer){ // Main update loop 
 
    globalTime = timer; 
 
    display(); // call demo code 
 
    // continue until mouse right down 
 
    if (!(mouse.buttonRaw & 2)) { requestAnimationFrame(update); } else { done(); } 
 
} 
 
requestAnimationFrame(update); 
 

 
/** SimpleFullCanvasMouse.js end **/

बदलने के लिए दिखाई देगा
संबंधित मुद्दे