简体   繁体   English

HTML5 Canvas:使用构造函数创建复杂的 Canvas 形状

[英]HTML5 Canvas: Using constructor functions to create complex Canvas shapes

I'm currently working on a HTML5 Canvas project (I wrote a separate question about it here ).我目前正在研究 HTML5 Canvas 项目(我在这里写了一个单独的问题)。 I think one of the solutions to the problems I am facing would be to create a reference for the path (saved as an object), and use the method ispointinpath to check if my mouse position is within the path or not – if its not, it resets the game.我认为我面临的问题的解决方案之一是为路径创建一个引用(保存为对象),并使用方法ispointinpath检查我的鼠标 position 是否在路径内 - 如果不是,它重置游戏。

I took a stab at creating a constructor function for a complex path shape.我尝试为复杂的路径形状创建构造函数 function。 Here's what the complex shape looks like as raw code:以下是复杂形状作为原始代码的样子:

 var canvas = document.querySelector('canvas'); // returning a drawing context to a variable 'c' // allows you to draw 2d elements var c = canvas.getContext('2d'); canvas.width = 1000; canvas.height = 700; canvas.style.width = 1000; canvas.style.height = 700; c.beginPath(); c.moveTo(350, 650); //start c.lineTo(350, 200); c.lineTo(900, 200); c.lineTo(900, 250); c.lineTo(700, 250); c.lineTo(600, 250); c.lineTo(600, 650); c.fillStyle = "#C1EEFF"; c.fill();
 <canvas></canvas>

Here's what it looks like as a constructor function that I tried to make:这是我尝试制作的构造函数 function 的样子:

 var canvas = document.querySelector('canvas'); // returning a drawing context to a variable 'c' // allows you to draw 2d elements var c = canvas.getContext('2d'); canvas.width = 1000; canvas.height = 700; canvas.style.width = 1000; canvas.style.height = 700; var points = [(350, 200), (900, 200), (900, 250), (700, 250), (600, 250), (600, 650)]; function Path(startX, startY, array, color){ c.beginPath(); c.moveTo(startX, startY); // For however many element pairs in the array, create a lineTo statement for(i = 1; i < array.length; i++){ c.lineTo(array[i][0], array[i][1]); } c.fillStyle = color; c.fill(); } var blue = new Path(350, 200, points, '#C1EEFF');
 <canvas></canvas>

It doesn't seem to be working.它似乎不起作用。 Does anyone know why that is?有谁知道这是为什么? Also, what would be the best syntax for what I'm trying to do?另外,对于我正在尝试做的事情,最好的语法是什么?

It would be better if you use an object with position x, y如果您将 object 与 position x, y 一起使用会更好

 var canvas = document.querySelector("canvas"); // returning a drawing context to a variable 'c' // allows you to draw 2d elements var c = canvas.getContext("2d"); canvas.width = 1000; canvas.height = 700; canvas.style.width = 1000; canvas.style.height = 700; var points = [ { x: 350, y: 200 }, { x: 900, y: 200 }, { x: 900, y: 250 }, { x: 700, y: 250 }, { x: 600, y: 250 }, { x: 600, y: 650 } ]; function Path(startX, startY, array, color) { c.beginPath(); c.moveTo(startX, startY); // For however many element pairs in the array, create a lineTo statement for (var i = 1; i < array.length; i++) { c.lineTo(array[i].x, array[i].y); } c.fillStyle = color; c.fill(); } var blue = new Path(350, 200, points, "#C1EEFF");
 <canvas></canvas>

First issue is your points array:第一个问题是您的积分数组:
var points = [(350, 200), (900, 200),...
that is not a correct bi-dimensional array, maybe you meant:这不是一个正确的二维数组,也许你的意思是:
var points = [[350, 200], [900, 200],...

also in your code Path is a function not a class, not sure why you doing new Path(...) maybe you got that mixed with new Path2D() but that is completely different...同样在您的代码Path中是 function 而不是 class,不确定您为什么要使用new Path(...)也许您将它与new Path2D()混合在一起,但这完全不同...
Look at the parameters for isPointInPath:查看isPointInPath的参数:
https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath#syntax https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/isPointInPath#syntax

Here is a working example这是一个工作示例

 var canvas = document.querySelector('canvas'); var c = canvas.getContext('2d'); canvas.width = 1000; canvas.height = 700; // Function to generate a Path2D object function Path(array) { let path = new Path2D(); path.moveTo(array[0][0], array[0][1]); for (i = 1; i < array.length; i++) { path.lineTo(array[i][0], array[i][1]); } path.lineTo(array[0][0], array[0][1]); return path } //Create the paths var big = [[350,200], [900,200], [900,250], [700,250], [600,250], [600,650], [350,650]]; var blue = Path(big); var triangle = [[25,10], [70,10], [90,85]]; var red = Path(triangle); // Draw all the paths c.beginPath() c.fillStyle = "blue"; c.fill(blue); c.beginPath() c.fillStyle = "red"; c.fill(red); // use isPointInPath console.log(c.isPointInPath(blue, 10, 10)) console.log(c.isPointInPath(blue, 351,201))
 <canvas></canvas>


Now on the now closed question my suggestion to using isPointInPath is to improve scalability, you had a bunch of hard coded if statement, that approach for more complex polygons just would not do... BUT you still have the problem in your game how to handle the transition between levels, that was the root problem on that question.现在,关于现在已结束的问题,我对使用isPointInPath的建议是提高可伸缩性,你有一堆硬编码的 if 语句,这种方法用于更复杂的多边形是行不通的......但你的游戏中仍然存在问题如何处理级别之间的转换,这是该问题的根本问题。

You seem to be trying to access your array coordinates using this syntax array[i][0], array[i][1] however your array is NOT an array of arrays it is an array of parenthesis.您似乎正在尝试使用此语法 array[i][0], array[i][1] 访问您的数组坐标,但是您的数组不是 arrays 的数组,它是括号数组。 I don't have time to play with it but try making it an array of arrays so you can then access element [0] and [1].我没有时间玩它,但试着让它成为一个 arrays 的数组,这样你就可以访问元素 [0] 和 [1]。

[[350, 200], [400, 250]] etc [[350, 200], [400, 250]] 等

EDIT: I am providing an ES6 class to create your maps.编辑:我提供 ES6 class 来创建您的地图。 This is just another option on top of the others provided here.这只是此处提供的其他选项之上的另一个选项。

const canvas = document.querySelector('canvas');
const c = canvas.getContext('2d');
canvas.width = 1000;
canvas.height = 700;
 
let points = [[300, 400], [400, 400], [400, 350], [400, 250], [700, 250], [700, 150], [750, 150], [750, 50], [775, 50], [775, 175], [725, 175], [725, 400], [500, 400], [500, 500], [500, 650], [300, 650] ];
let points2 = [[750, 50], [775, 50], [775, 100], [750, 100]];

class Map {
  constructor(start_x, start_y, arr, c) {
    this.start_x = start_x;
    this.start_y = start_y;
    this.arr = arr;
    this.color = c;
  }
  draw() {
    c.beginPath();
    c.moveTo(this.start_x, this.start_y); //start
    this.arr.forEach(point => c.lineTo(point[0], point[1]));
    c.fillStyle = this.color;
    c.fill();
    c.closePath(); 
  }
}
let map1 = new Map(300, 650, points, 'blue');
let map1Finish = new Map(750, 100, points2, 'red');
map1.draw();
map1Finish.draw();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM