खोज…


कैनवस पर वास्तव में कैसे आकार और छवियां (!) "चाल"

एक समस्या: कैनवस केवल पिक्सल को याद करता है, न कि आकृतियों या चित्रों को

यह एक गोलाकार समुद्र तट गेंद की एक छवि है, और निश्चित रूप से, आप छवि के चारों ओर गेंद को नहीं खींच सकते।

यहाँ छवि विवरण दर्ज करें

यह आपको आश्चर्यचकित कर सकता है कि एक छवि की तरह, यदि आप कैनवास पर एक वृत्त खींचते हैं तो आप उस वृत्त को कैनवास के चारों ओर नहीं खींच सकते। ऐसा इसलिए है क्योंकि कैनवस को यह याद नहीं होगा कि उसने सर्कल कहां बनाया है।

// this arc (==circle) is not draggable!!
context.beginPath();
context.arc(20, 30, 15, 0, Math.PI*2);
context.fillStyle='blue';
context.fill();

कैनवास क्या नहीं जानता ...

  • ... जहाँ आपने वृत्त बनाया है (यह x, y = [20,30] नहीं जानता है)।
  • ... वृत्त का आकार (यह त्रिज्या = 15 नहीं जानता है)।
  • ... वृत्त का रंग। (यह नहीं जानता कि चक्र नीला है)।

कैनवस क्या जानता है ...

कैनवस हर पिक्सेल के रंग को जानता है, जो उसकी सतह को खींच रहा है।

कैनवास आपको बता सकता है कि x, y == [20,30] पर एक ब्लू पिक्सेल है, लेकिन यह नहीं जानता कि यह ब्लू पिक्सेल किसी सर्कल का हिस्सा है या नहीं।

इसका क्या मतलब है...

इसका मतलब है कि कैनवस पर खींची गई हर चीज स्थायी है: अचल और अपरिवर्तनीय।

  • कैनवस सर्कल को स्थानांतरित नहीं कर सकते हैं या सर्कल का आकार बदल नहीं सकते हैं।
  • कैनवस सर्कल को फिर से शुरू नहीं कर सकते हैं या सर्कल को मिटा नहीं सकते हैं।
  • यदि माउस सर्कल पर मँडरा रहा है तो कैनवास यह नहीं कह सकता।
  • अगर सर्कल दूसरे सर्कल से टकरा रहा है तो कैनवस नहीं कह सकता।
  • कैनवास उपयोगकर्ता को कैनवस के चारों ओर के घेरे को खींचने नहीं दे सकता है।

लेकिन कैनवस आंदोलन का ILLUSION दे सकता है

कैनवस लगातार चक्र को मिटाकर और इसे एक अलग स्थिति में लाकर आंदोलन का भ्रम दे सकता है। प्रति सेकंड कई बार कैनवस को फिर से लाल करके, आंख को कैनवस के पार सर्कल चाल को देखने में मूर्ख बनाया जाता है।

  • कैनवास को मिटा दें

  • सर्कल की स्थिति को अपडेट करें

  • इसमें सर्कल को फिर से नया करें

  • दोहराना, दोहराना, दोहराना ...

यह कोड नई स्थितियों में एक सर्कल को लगातार लाल करके आंदोलन का भ्रम देता है।

// create a canvas
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
ctx.fillStyle='red';
document.body.appendChild(canvas);

// a variable indicating a circle's X position
var circleX=20;

// start animating the circle across the canvas
// by continuously erasing & redrawing the circle
// in new positions
requestAnimationFrame(animate);

function animate(){
    // update the X position of the circle
    circleX++;      
    // redraw the circle in it's new position
    ctx.clearRect(0,0,canvas.width,canvas.height);
    ctx.beginPath();
    ctx.arc( circleX, 30,15,0,Math.PI*2 );
    ctx.fill();
    // request another animate() loop
    requestAnimationFrame(animate);
}

कैनवस के चारों ओर घेरे और आयतें खींचना

एक "आकृति" क्या है?

आप आमतौर पर प्रत्येक आकृति का प्रतिनिधित्व करते हुए जावास्क्रिप्ट "आकृति" ऑब्जेक्ट बनाकर अपनी आकृतियों को बचाते हैं।

var myCircle = { x:30, y:20, radius:15 };

बेशक, आप वास्तव में आकार नहीं बचा रहे हैं। इसके बजाय, आप आकृतियों को कैसे आकर्षित करें, इसकी परिभाषा सहेज रहे हैं।

फिर आसान संदर्भ के लिए हर आकृति-वस्तु को एक सरणी में रखें।

// save relevant information about shapes drawn on the canvas
var shapes=[];

// define one circle and save it in the shapes[] array
shapes.push( {x:10, y:20, radius:15, fillcolor:'blue'} );

// define one rectangle and save it in the shapes[] array
shapes.push( {x:10, y:100, width:50, height:35, fillcolor:'red'} );

ड्रैगिंग करने के लिए माउस इवेंट्स का उपयोग करना

एक आकृति या छवि को खींचकर इन माउस घटनाओं की प्रतिक्रिया की आवश्यकता होती है:

मूसडाउन पर:

यदि कोई आकृति माउस के नीचे है तो परीक्षण करें। यदि कोई आकृति माउस के नीचे है, तो उपयोगकर्ता उस आकृति को खींचने का इरादा रखता है। तो उस आकृति का संदर्भ रखें और एक सच्चा / गलत isDragging ध्वज सेट करें जो यह दर्शाता है कि एक ड्रैग प्रक्रिया में है।

मूसमोव पर:

उस दूरी की गणना करें जो माउस को अंतिम mousemove घटना के बाद से घसीटा गया है और उस दूरी से घसीट की स्थिति को बदल दें। आकृति की स्थिति बदलने के लिए, आप उस आकृति की वस्तु में x,y स्थिति गुण बदलते हैं।

माउसअप या माउसआउट पर:

उपयोगकर्ता ड्रैग ऑपरेशन को रोकने का इरादा कर रहा है, इसलिए "डैगिंग" ध्वज को साफ़ करें। खींचना पूरा हो गया है।

डेमो: कैनवास पर घेरे और आयतों को खींचना

यह डेमो माउस की घटनाओं का जवाब देकर और समाशोधन और पुनर्वितरण द्वारा आंदोलन का भ्रम देकर कैनवास पर हलकों और आयतों को खींचता है।

// canvas related vars
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
document.body.appendChild(canvas);
canvas.style.border='1px solid red';

// used to calc canvas position relative to window
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
canvas.onresize=function(e){ reOffset(); }

// save relevant information about shapes drawn on the canvas
var shapes=[];
// define one circle and save it in the shapes[] array
shapes.push( {x:30, y:30, radius:15, color:'blue'} );
// define one rectangle and save it in the shapes[] array
shapes.push( {x:100, y:-1, width:75, height:35, color:'red'} );

// drag related vars
var isDragging=false;
var startX,startY;

// hold the index of the shape being dragged (if any)
var selectedShapeIndex;

// draw the shapes on the canvas
drawAll();

// listen for mouse events
canvas.onmousedown=handleMouseDown;
canvas.onmousemove=handleMouseMove;
canvas.onmouseup=handleMouseUp;
canvas.onmouseout=handleMouseOut;

// given mouse X & Y (mx & my) and shape object
// return true/false whether mouse is inside the shape
function isMouseInShape(mx,my,shape){
    if(shape.radius){
        // this is a circle
        var dx=mx-shape.x;
        var dy=my-shape.y;
        // math test to see if mouse is inside circle
        if(dx*dx+dy*dy<shape.radius*shape.radius){
            // yes, mouse is inside this circle
            return(true);
        }
    }else if(shape.width){
        // this is a rectangle
        var rLeft=shape.x;
        var rRight=shape.x+shape.width;
        var rTop=shape.y;
        var rBott=shape.y+shape.height;
        // math test to see if mouse is inside rectangle
        if( mx>rLeft && mx<rRight && my>rTop && my<rBott){
            return(true);
        }
    }
    // the mouse isn't in any of the shapes
    return(false);
}

function handleMouseDown(e){
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // calculate the current mouse position
    startX=parseInt(e.clientX-offsetX);
    startY=parseInt(e.clientY-offsetY);
    // test mouse position against all shapes
    // post result if mouse is in a shape
    for(var i=0;i<shapes.length;i++){
        if(isMouseInShape(startX,startY,shapes[i])){
            // the mouse is inside this shape
            // select this shape
            selectedShapeIndex=i;
            // set the isDragging flag
            isDragging=true;
            // and return (==stop looking for 
            //     further shapes under the mouse)
            return;
        }
    }
}

function handleMouseUp(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // the drag is over -- clear the isDragging flag
    isDragging=false;
}

function handleMouseOut(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // the drag is over -- clear the isDragging flag
    isDragging=false;
}

function handleMouseMove(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // calculate the current mouse position         
    mouseX=parseInt(e.clientX-offsetX);
    mouseY=parseInt(e.clientY-offsetY);
    // how far has the mouse dragged from its previous mousemove position?
    var dx=mouseX-startX;
    var dy=mouseY-startY;
    // move the selected shape by the drag distance
    var selectedShape=shapes[selectedShapeIndex];
    selectedShape.x+=dx;
    selectedShape.y+=dy;
    // clear the canvas and redraw all shapes
    drawAll();
    // update the starting drag position (== the current mouse position)
    startX=mouseX;
    startY=mouseY;
}

// clear the canvas and 
// redraw all shapes in their current positions
function drawAll(){
    ctx.clearRect(0,0,cw,ch);
    for(var i=0;i<shapes.length;i++){
        var shape=shapes[i];
        if(shape.radius){
            // it's a circle
            ctx.beginPath();
            ctx.arc(shape.x,shape.y,shape.radius,0,Math.PI*2);
            ctx.fillStyle=shape.color;
            ctx.fill();
        }else if(shape.width){
            // it's a rectangle
            ctx.fillStyle=shape.color;
            ctx.fillRect(shape.x,shape.y,shape.width,shape.height);
        }
    }
}

कैनवास के चारों ओर अनियमित आकृतियों को खींचना

अधिकांश कैनवस चित्र या तो आयताकार (आयत, चित्र, पाठ-ब्लॉक) या परिपत्र (सर्कल) हैं।

मंडलियों और आयतों में यह जांचने के लिए गणितीय परीक्षण हैं कि माउस उनके अंदर है या नहीं। यह परीक्षण हलकों और आयतों को आसान, त्वरित और कुशल बनाता है। आप सेकंड के एक हिस्से में सैकड़ों सर्कल या आयतों को "हिट-टेस्ट" कर सकते हैं।

आप अनियमित आकृतियों को भी खींच सकते हैं। लेकिन अनियमित आकृतियों का कोई त्वरित गणितीय हिट-परीक्षण नहीं है। सौभाग्य से, अनियमित आकृतियों में एक बिंदु (माउस) आकार के अंदर है या नहीं यह निर्धारित करने के लिए एक अंतर्निहित हिट-परीक्षण है: context.isPointInPath । जबकि isPointInPath अच्छी तरह से काम करता है, यह लगभग गणितीय रूप से हिट-परीक्षणों के रूप में कुशल नहीं है - यह अक्सर शुद्ध गणितीय हिट-परीक्षणों की तुलना में 10X तक धीमा होता है।

एक आवश्यकता का उपयोग करते समय isPointInPath है कि आप "को फिर से परिभाषित" पथ कॉल करने से पहले तुरंत परीक्षण किया जा रहा है चाहिए isPointInPath । "रिडिफाइन" का अर्थ है कि आपको पथ ड्राइंग कमांड (ऊपर के रूप में) जारी करना चाहिए, लेकिन आपको isPointInPath साथ परीक्षण करने से पहले पथ को स्ट्रोक () या भरने की आवश्यकता नहीं है। इस तरह आप पहले से तैयार किए गए रास्तों का परीक्षण कर सकते हैं, उन पिछले पथों को अधिलेखित करने (स्ट्रोक / भरने) के बिना जो स्वयं कैनवस पर हैं।

अनियमित आकार हर रोज त्रिकोण के रूप में आम होने की जरूरत नहीं है। आप किसी भी बेतहाशा अनियमित पथ पर हिट-टेस्ट कर सकते हैं।

यह एनोटेट उदाहरण दिखाता है कि अनियमित पथ आकृतियों के साथ-साथ मंडलियों और आयतों को कैसे खींचें:

// canvas related vars
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
document.body.appendChild(canvas);
canvas.style.border='1px solid red';

// used to calc canvas position relative to window
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
canvas.onresize=function(e){ reOffset(); }

// save relevant information about shapes drawn on the canvas
var shapes=[];
// define one circle and save it in the shapes[] array
shapes.push( {x:20, y:20, radius:15, color:'blue'} );
// define one rectangle and save it in the shapes[] array
shapes.push( {x:100, y:-1, width:75, height:35, color:'red'} );
// define one triangle path and save it in the shapes[] array
shapes.push( {x:0, y:0, points:[{x:50,y:30},{x:75,y:60},{x:25,y:60}],color:'green'} );

// drag related vars
var isDragging=false;
var startX,startY;

// hold the index of the shape being dragged (if any)
var selectedShapeIndex;

// draw the shapes on the canvas
drawAll();

// listen for mouse events
canvas.onmousedown=handleMouseDown;
canvas.onmousemove=handleMouseMove;
canvas.onmouseup=handleMouseUp;
canvas.onmouseout=handleMouseOut;

// given mouse X & Y (mx & my) and shape object
// return true/false whether mouse is inside the shape
function isMouseInShape(mx,my,shape){
    if(shape.radius){
        // this is a circle
        var dx=mx-shape.x;
        var dy=my-shape.y;
        // math test to see if mouse is inside circle
        if(dx*dx+dy*dy<shape.radius*shape.radius){
            // yes, mouse is inside this circle
            return(true);
        }
    }else if(shape.width){
        // this is a rectangle
        var rLeft=shape.x;
        var rRight=shape.x+shape.width;
        var rTop=shape.y;
        var rBott=shape.y+shape.height;
        // math test to see if mouse is inside rectangle
        if( mx>rLeft && mx<rRight && my>rTop && my<rBott){
            return(true);
        }
    }else if(shape.points){
        // this is a polyline path
        // First redefine the path again (no need to stroke/fill!)
        defineIrregularPath(shape);
        // Then hit-test with isPointInPath
        if(ctx.isPointInPath(mx,my)){
            return(true);
        }                
    }
    // the mouse isn't in any of the shapes
    return(false);
}

function handleMouseDown(e){
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // calculate the current mouse position
    startX=parseInt(e.clientX-offsetX);
    startY=parseInt(e.clientY-offsetY);
    // test mouse position against all shapes
    // post result if mouse is in a shape
    for(var i=0;i<shapes.length;i++){
        if(isMouseInShape(startX,startY,shapes[i])){
            // the mouse is inside this shape
            // select this shape
            selectedShapeIndex=i;
            // set the isDragging flag
            isDragging=true;
            // and return (==stop looking for 
            //     further shapes under the mouse)
            return;
        }
    }
}

function handleMouseUp(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // the drag is over -- clear the isDragging flag
    isDragging=false;
}

function handleMouseOut(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // the drag is over -- clear the isDragging flag
    isDragging=false;
}

function handleMouseMove(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // calculate the current mouse position         
    mouseX=parseInt(e.clientX-offsetX);
    mouseY=parseInt(e.clientY-offsetY);
    // how far has the mouse dragged from its previous mousemove position?
    var dx=mouseX-startX;
    var dy=mouseY-startY;
    // move the selected shape by the drag distance
    var selectedShape=shapes[selectedShapeIndex];
    selectedShape.x+=dx;
    selectedShape.y+=dy;
    // clear the canvas and redraw all shapes
    drawAll();
    // update the starting drag position (== the current mouse position)
    startX=mouseX;
    startY=mouseY;
}

// clear the canvas and 
// redraw all shapes in their current positions
function drawAll(){
    ctx.clearRect(0,0,cw,ch);
    for(var i=0;i<shapes.length;i++){
        var shape=shapes[i];
        if(shape.radius){
            // it's a circle
            ctx.beginPath();
            ctx.arc(shape.x,shape.y,shape.radius,0,Math.PI*2);
            ctx.fillStyle=shape.color;
            ctx.fill();
        }else if(shape.width){
            // it's a rectangle
            ctx.fillStyle=shape.color;
            ctx.fillRect(shape.x,shape.y,shape.width,shape.height);
        }else if(shape.points){
            // its a polyline path
            defineIrregularPath(shape);
            ctx.fillStyle=shape.color;
            ctx.fill();
        }
    }
}

function defineIrregularPath(shape){
    var points=shape.points;
    ctx.beginPath();
    ctx.moveTo(shape.x+points[0].x,shape.y+points[0].y);
    for(var i=1;i<points.length;i++){
        ctx.lineTo(shape.x+points[i].x,shape.y+points[i].y);
    }
    ctx.closePath();
}

कैनवस के आसपास की तस्वीरें खींचना

इस उदाहरण को कैनवस के चारों ओर आकृतियाँ खींचने के सामान्य विवरण के लिए देखें।

यह एनोटेट उदाहरण दिखाता है कि कैनवस के आसपास की छवियों को कैसे खींचें

// canvas related vars
var canvas=document.createElement("canvas");
var ctx=canvas.getContext("2d");
canvas.width=378;
canvas.height=378;
var cw=canvas.width;
var ch=canvas.height;
document.body.appendChild(canvas);
canvas.style.border='1px solid red';

// used to calc canvas position relative to window
function reOffset(){
    var BB=canvas.getBoundingClientRect();
    offsetX=BB.left;
    offsetY=BB.top;        
}
var offsetX,offsetY;
reOffset();
window.onscroll=function(e){ reOffset(); }
window.onresize=function(e){ reOffset(); }
canvas.onresize=function(e){ reOffset(); }

// save relevant information about shapes drawn on the canvas
var shapes=[];

// drag related vars
var isDragging=false;
var startX,startY;

// hold the index of the shape being dragged (if any)
var selectedShapeIndex;

// load the image
var card=new Image();
card.onload=function(){
    // define one image and save it in the shapes[] array
    shapes.push( {x:30, y:10, width:127, height:150, image:card} );
    // draw the shapes on the canvas
    drawAll();
    // listen for mouse events
    canvas.onmousedown=handleMouseDown;
    canvas.onmousemove=handleMouseMove;
    canvas.onmouseup=handleMouseUp;
    canvas.onmouseout=handleMouseOut;
};
// put your image src here!
card.src='https://dl.dropboxusercontent.com/u/139992952/stackoverflow/card.png';


// given mouse X & Y (mx & my) and shape object
// return true/false whether mouse is inside the shape
function isMouseInShape(mx,my,shape){
    // is this shape an image?
    if(shape.image){
        // this is a rectangle
        var rLeft=shape.x;
        var rRight=shape.x+shape.width;
        var rTop=shape.y;
        var rBott=shape.y+shape.height;
        // math test to see if mouse is inside image
        if( mx>rLeft && mx<rRight && my>rTop && my<rBott){
            return(true);
        }
    }
    // the mouse isn't in any of this shapes
    return(false);
}

function handleMouseDown(e){
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // calculate the current mouse position
    startX=parseInt(e.clientX-offsetX);
    startY=parseInt(e.clientY-offsetY);
    // test mouse position against all shapes
    // post result if mouse is in a shape
    for(var i=0;i<shapes.length;i++){
        if(isMouseInShape(startX,startY,shapes[i])){
            // the mouse is inside this shape
            // select this shape
            selectedShapeIndex=i;
            // set the isDragging flag
            isDragging=true;
            // and return (==stop looking for 
            //     further shapes under the mouse)
            return;
        }
    }
}

function handleMouseUp(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // the drag is over -- clear the isDragging flag
    isDragging=false;
}

function handleMouseOut(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // the drag is over -- clear the isDragging flag
    isDragging=false;
}

function handleMouseMove(e){
    // return if we're not dragging
    if(!isDragging){return;}
    // tell the browser we're handling this event
    e.preventDefault();
    e.stopPropagation();
    // calculate the current mouse position         
    mouseX=parseInt(e.clientX-offsetX);
    mouseY=parseInt(e.clientY-offsetY);
    // how far has the mouse dragged from its previous mousemove position?
    var dx=mouseX-startX;
    var dy=mouseY-startY;
    // move the selected shape by the drag distance
    var selectedShape=shapes[selectedShapeIndex];
    selectedShape.x+=dx;
    selectedShape.y+=dy;
    // clear the canvas and redraw all shapes
    drawAll();
    // update the starting drag position (== the current mouse position)
    startX=mouseX;
    startY=mouseY;
}

// clear the canvas and 
// redraw all shapes in their current positions
function drawAll(){
    ctx.clearRect(0,0,cw,ch);
    for(var i=0;i<shapes.length;i++){
        var shape=shapes[i];
        if(shape.image){
            // it's an image
            ctx.drawImage(shape.image,shape.x,shape.y);
        }
    }
}


Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow