簡體   English   中英

如何在JavaScript中將圖像用作畫布

[英]how to use image as a canvas in javascript

我有一個腳本,用來在畫布上繪制矩形。 用戶可以拖動/重新放置繪制的矩形,也可以通過雙擊添加新的矩形。 現在,我想在背景上添加圖像,即,我不想使用普通畫布,而是要在上面放置矩形的圖像。

我要構建的是這些矩形對應於圖像的特定區域。 加載此圖像和矩形后,如果區域和矩形未對齊,則用戶應該能夠正確地重新放置它們。

這是我的代碼:

 //Box object to hold data for all drawn rects function Box() { this.x = 0; this.y = 0; this.w = 1; // default width and height? this.h = 1; this.fill = '#444444'; } //Initialize a new Box, add it, and invalidate the canvas function addRect(x, y, w, h, fill) { var rect = new Box; rect.x = x; rect.y = y; rect.w = w rect.h = h; rect.fill = fill; boxes.push(rect); invalidate(); } // holds all our rectangles var boxes = []; var canvas; var ctx; var WIDTH; var HEIGHT; var INTERVAL = 20; // how often, in milliseconds, we check to see if a redraw is needed var isDrag = false; var mx, my; // mouse coordinates // when set to true, the canvas will redraw everything // invalidate() just sets this to false right now // we want to call invalidate() whenever we make a change var canvasValid = false; // The node (if any) being selected. // If in the future we want to select multiple objects, this will get turned into an array var mySel; // The selection color and width. Right now we have a red selection with a small width var mySelColor = '#CC0000'; var mySelWidth = 2; // we use a fake canvas to draw individual shapes for selection testing var ghostcanvas; var gctx; // fake canvas context // since we can drag from anywhere in a node // instead of just its x/y corner, we need to save // the offset of the mouse when we start dragging. var offsetx, offsety; // Padding and border style widths for mouse offsets var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop; // initialize our canvas, add a ghost canvas, set draw loop // then add everything we want to intially exist on the canvas function init() { // canvas = fill_canvas(); canvas = document.getElementById('canvas'); HEIGHT = canvas.height; WIDTH = canvas.width; ctx = canvas.getContext('2d'); ghostcanvas = document.createElement('canvas'); ghostcanvas.height = HEIGHT; ghostcanvas.width = WIDTH; gctx = ghostcanvas.getContext('2d'); //fixes a problem where double clicking causes text to get selected on the canvas canvas.onselectstart = function () { return false; } // fixes mouse co-ordinate problems when there's a border or padding // see getMouse for more detail if (document.defaultView && document.defaultView.getComputedStyle) { stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0; stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0; styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0; styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0; } // make draw() fire every INTERVAL milliseconds setInterval(draw, INTERVAL); // set our events. Up and down are for dragging, // double click is for making new boxes canvas.onmousedown = myDown; canvas.onmouseup = myUp; canvas.ondblclick = myDblClick; // add custom initialization here: // add an orange rectangle addRect(200, 200, 200, 200, '#FFC02B'); // add a smaller blue rectangle addRect(25, 90, 250, 150 , '#2BB8FF'); } //wipes the canvas context function clear(c) { c.clearRect(0, 0, WIDTH, HEIGHT); } // While draw is called as often as the INTERVAL variable demands, // It only ever does something if the canvas gets invalidated by our code function draw() { if (canvasValid == false) { clear(ctx); // Add stuff you want drawn in the background all the time here // draw all boxes var l = boxes.length; for (var i = 0; i < l; i++) { drawshape(ctx, boxes[i], boxes[i].fill); } // draw selection // right now this is just a stroke along the edge of the selected box if (mySel != null) { ctx.strokeStyle = mySelColor; ctx.lineWidth = mySelWidth; ctx.strokeRect(mySel.x,mySel.y,mySel.w,mySel.h); } // Add stuff you want drawn on top all the time here canvasValid = true; } } // Draws a single shape to a single context // draw() will call this with the normal canvas // myDown will call this with the ghost canvas function drawshape(context, shape, fill) { context.fillStyle = fill; // We can skip the drawing of elements that have moved off the screen: if (shape.x > WIDTH || shape.y > HEIGHT) return; if (shape.x + shape.w < 0 || shape.y + shape.h < 0) return; context.fillRect(shape.x,shape.y,shape.w,shape.h); } // Happens when the mouse is moving inside the canvas function myMove(e){ if (isDrag){ getMouse(e); mySel.x = mx - offsetx; mySel.y = my - offsety; // something is changing position so we better invalidate the canvas! invalidate(); } } // Happens when the mouse is clicked in the canvas function myDown(e){ getMouse(e); clear(gctx); var l = boxes.length; for (var i = l-1; i >= 0; i--) { // draw shape onto ghost context drawshape(gctx, boxes[i], 'black'); // get image data at the mouse x,y pixel var imageData = gctx.getImageData(mx, my, 1, 1); var index = (mx + my * imageData.width) * 4; // if the mouse pixel exists, select and break if (imageData.data[3] > 0) { mySel = boxes[i]; offsetx = mx - mySel.x; offsety = my - mySel.y; mySel.x = mx - offsetx; mySel.y = my - offsety; isDrag = true; canvas.onmousemove = myMove; invalidate(); clear(gctx); return; } } // havent returned means we have selected nothing mySel = null; // clear the ghost canvas for next time clear(gctx); // invalidate because we might need the selection border to disappear invalidate(); } function myUp(){ isDrag = false; canvas.onmousemove = null; } // adds a new node function myDblClick(e) { getMouse(e); // for this method width and height determine the starting X and Y, too. // so I left them as vars in case someone wanted to make them args for something and copy this code var width = 150; var height = 100; addRect(mx - (width / 2), my - (height / 2), width, height, '#77DD44'); } function invalidate() { canvasValid = false; } // Sets mx,my to the mouse position relative to the canvas // unfortunately this can be tricky, we have to worry about padding and borders function getMouse(e) { var element = canvas, offsetX = 0, offsetY = 0; if (element.offsetParent) { do { offsetX += element.offsetLeft; offsetY += element.offsetTop; } while ((element = element.offsetParent)); } // Add padding and border style widths to offset offsetX += stylePaddingLeft; offsetY += stylePaddingTop; offsetX += styleBorderLeft; offsetY += styleBorderTop; mx = e.pageX - offsetX; my = e.pageY - offsetY } // If you dont want to use <body onLoad='init()'> // You could uncomment this init() reference and place the script reference inside the body tag init(); 
 <!DOCTYPE html> <html> <head> <title>js</title> </head> <body> <canvas id="canvas" width="400" height="300"> This text is displayed if your browser does not support HTML5 Canvas. </canvas> </body> </html> 

如果在html中加載了圖片,則下面的代碼段應該可以使用。

代碼中有兩個更改:

  • 將圖像加載到變量中
  • 使用ctx.drawImage(im, 0, 0)將圖像繪制到畫布上

 //Box object to hold data for all drawn rects function Box() { this.x = 0; this.y = 0; this.w = 1; // default width and height? this.h = 1; this.fill = '#444444'; } //Initialize a new Box, add it, and invalidate the canvas function addRect(x, y, w, h, fill) { var rect = new Box; rect.x = x; rect.y = y; rect.w = w rect.h = h; rect.fill = fill; boxes.push(rect); invalidate(); } //*************************** // This will load the image into the variable "im" var im = document.getElementById("myImage"); //*************************** // holds all our rectangles var boxes = []; var canvas; var ctx; var WIDTH; var HEIGHT; var INTERVAL = 20; // how often, in milliseconds, we check to see if a redraw is needed var isDrag = false; var mx, my; // mouse coordinates // when set to true, the canvas will redraw everything // invalidate() just sets this to false right now // we want to call invalidate() whenever we make a change var canvasValid = false; // The node (if any) being selected. // If in the future we want to select multiple objects, this will get turned into an array var mySel; // The selection color and width. Right now we have a red selection with a small width var mySelColor = '#CC0000'; var mySelWidth = 2; // we use a fake canvas to draw individual shapes for selection testing var ghostcanvas; var gctx; // fake canvas context // since we can drag from anywhere in a node // instead of just its x/y corner, we need to save // the offset of the mouse when we start dragging. var offsetx, offsety; // Padding and border style widths for mouse offsets var stylePaddingLeft, stylePaddingTop, styleBorderLeft, styleBorderTop; // initialize our canvas, add a ghost canvas, set draw loop // then add everything we want to intially exist on the canvas function init() { // canvas = fill_canvas(); canvas = document.getElementById('canvas'); HEIGHT = canvas.height; WIDTH = canvas.width; ctx = canvas.getContext('2d'); ghostcanvas = document.createElement('canvas'); ghostcanvas.height = HEIGHT; ghostcanvas.width = WIDTH; gctx = ghostcanvas.getContext('2d'); //fixes a problem where double clicking causes text to get selected on the canvas canvas.onselectstart = function () { return false; } // fixes mouse co-ordinate problems when there's a border or padding // see getMouse for more detail if (document.defaultView && document.defaultView.getComputedStyle) { stylePaddingLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingLeft'], 10) || 0; stylePaddingTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['paddingTop'], 10) || 0; styleBorderLeft = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderLeftWidth'], 10) || 0; styleBorderTop = parseInt(document.defaultView.getComputedStyle(canvas, null)['borderTopWidth'], 10) || 0; } // make draw() fire every INTERVAL milliseconds setInterval(draw, INTERVAL); // set our events. Up and down are for dragging, // double click is for making new boxes canvas.onmousedown = myDown; canvas.onmouseup = myUp; canvas.ondblclick = myDblClick; // add custom initialization here: // add an orange rectangle addRect(200, 200, 200, 200, '#FFC02B'); // add a smaller blue rectangle addRect(25, 90, 250, 150 , '#2BB8FF'); } //wipes the canvas context function clear(c) { c.clearRect(0, 0, WIDTH, HEIGHT); } // While draw is called as often as the INTERVAL variable demands, // It only ever does something if the canvas gets invalidated by our code function draw() { if (canvasValid == false) { clear(ctx); // Add stuff you want drawn in the background all the time here // draw all boxes var l = boxes.length; for (var i = 0; i < l; i++) { drawshape(ctx, boxes[i], boxes[i].fill); } // draw selection // right now this is just a stroke along the edge of the selected box if (mySel != null) { ctx.strokeStyle = mySelColor; ctx.lineWidth = mySelWidth; ctx.strokeRect(mySel.x,mySel.y,mySel.w,mySel.h); } // Add stuff you want drawn on top all the time here //You might want to change the size of the image //In that case use ctx.drawImage(im,0,0,width,height); //*************************** ctx.drawImage(im,0,0); //*************************** canvasValid = true; } } // Draws a single shape to a single context // draw() will call this with the normal canvas // myDown will call this with the ghost canvas function drawshape(context, shape, fill) { context.fillStyle = fill; // We can skip the drawing of elements that have moved off the screen: if (shape.x > WIDTH || shape.y > HEIGHT) return; if (shape.x + shape.w < 0 || shape.y + shape.h < 0) return; context.fillRect(shape.x,shape.y,shape.w,shape.h); } // Happens when the mouse is moving inside the canvas function myMove(e){ if (isDrag){ getMouse(e); mySel.x = mx - offsetx; mySel.y = my - offsety; // something is changing position so we better invalidate the canvas! invalidate(); } } // Happens when the mouse is clicked in the canvas function myDown(e){ getMouse(e); clear(gctx); var l = boxes.length; for (var i = l-1; i >= 0; i--) { // draw shape onto ghost context drawshape(gctx, boxes[i], 'black'); // get image data at the mouse x,y pixel var imageData = gctx.getImageData(mx, my, 1, 1); var index = (mx + my * imageData.width) * 4; // if the mouse pixel exists, select and break if (imageData.data[3] > 0) { mySel = boxes[i]; offsetx = mx - mySel.x; offsety = my - mySel.y; mySel.x = mx - offsetx; mySel.y = my - offsety; isDrag = true; canvas.onmousemove = myMove; invalidate(); clear(gctx); return; } } // havent returned means we have selected nothing mySel = null; // clear the ghost canvas for next time clear(gctx); // invalidate because we might need the selection border to disappear invalidate(); } function myUp(){ isDrag = false; canvas.onmousemove = null; } // adds a new node function myDblClick(e) { getMouse(e); // for this method width and height determine the starting X and Y, too. // so I left them as vars in case someone wanted to make them args for something and copy this code var width = 150; var height = 100; addRect(mx - (width / 2), my - (height / 2), width, height, '#77DD44'); } function invalidate() { canvasValid = false; } // Sets mx,my to the mouse position relative to the canvas // unfortunately this can be tricky, we have to worry about padding and borders function getMouse(e) { var element = canvas, offsetX = 0, offsetY = 0; if (element.offsetParent) { do { offsetX += element.offsetLeft; offsetY += element.offsetTop; } while ((element = element.offsetParent)); } // Add padding and border style widths to offset offsetX += stylePaddingLeft; offsetY += stylePaddingTop; offsetX += styleBorderLeft; offsetY += styleBorderTop; mx = e.pageX - offsetX; my = e.pageY - offsetY } // If you dont want to use <body onLoad='init()'> // You could uncomment this init() reference and place the script reference inside the body tag init(); 
 <!DOCTYPE html> <html> <head> <title>js</title> </head> <body> <canvas id="canvas" width="400" height="300"> This text is displayed if your browser does not support HTML5 Canvas. </canvas> <!-- This image will be displayed on the canvas --> <img id="myImage" src="image.jpg" style = "display: none"> </body> </html> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM