gpt4 book ai didi

javascript - 如何在javascript中使用图像作为 Canvas

转载 作者:行者123 更新时间:2023-11-28 03:48:50 25 4
gpt4 key购买 nike

我有一个脚本,用于在 Canvas 上绘制矩形。用户可以拖动/重新定位绘制的矩形,也可以通过双击添加新矩形。现在我想在背景上添加图像,也就是说,我不想使用普通 Canvas ,而是使用可以在其上放置矩形的图像。

我试图构建的是这些矩形对应于图像的特定区域。加载此图像和矩形后,如果区域和矩形未对齐,用户应该能够正确地重新定位它们。

这是我的代码:

//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) 将图像绘制到 Canvas 上

//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>

关于javascript - 如何在javascript中使用图像作为 Canvas ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48212281/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com