使用for循环的可缩放多边形网格 [英] Scalable polygon grid using for loop
问题描述
我想创建一个交互式数字画布,在网格中生成一系列接近方形的多边形。下面的jsFiddle显示了一个2x2网格系统的所述多边形。如果你检查代码或刷新页面,你会看到中心顶点是一个半随机生成点,4个相邻的多边形共享。
我想缩放这个网格到16×16附近的东西,每个内部顶点是半随机生成的,但是在当前状态下,完成的代码将是低效的,不灵活的和不可伸缩的。我知道有一个相对简单的解决方案,但考虑到我没有经验的for循环和数组,它目前超出了我的范围。非常感谢任何帮助。
<!doctype html>
< html>
< head>
< link rel =stylesheettype =text / cssmedia =allhref =css / reset.css/> <! - reset css - >
< script type =text / javascriptsrc =http://code.jquery.com/jquery.min.js>< / script>
< style>
body {background-color:ivory; }
#canvas {border:1px solid red;}
< / style>
< script>
$(function(){
var canvas = document.getElementById(canvas);
var ctx = canvas.getContext(2d);
//声明一个数组
var points = new Array(17);
for(var i = 0; i< points.length; i ++){
points [i] = new Array(17);
}
var sideLength = 20;
//填充数组
for(var y = 0; y <17; y ++){
for(var x = 0; x <17; x ++){
//创建随机半偏移网格点
var radius = 2.5 * random();
var radianAngle = 2 * Math.PI * Math.random();
var cx = x * sideLength + radius * Math.cos(radianAngle);
var cy = y * sideLength + radius * Math.sin(radianAngle);
//如果这是一个sidepoint,不偏移(边是直的)
if(x == 0){cx = 0; }
if(y == 0){cy = 0;}
if(x == 16){cx = x * sideLength;}
if = y * sideLength;}
//将此网格点添加到点数组
points [x] [y] = {x:cx + 10,y:cy + 10}
}
}
//行程每个单元格的四边
for(var y = 0; y <16; y ++){
(var x = 0; x <16; x ++){
strokeCell(x,y);
}
}
//绘制单元格的四边
function strokeCell(x,y){
var pt0 = points [x] [y];
var pt1 = points [x + 1] [y];
var pt2 = points [x + 1] [y + 1];
var pt3 = points [x] [y + 1];
ctx.beginPath();
ctx.moveTo(pt0.x,pt0.y);
ctx.lineTo(pt1.x,pt1.y);
ctx.lineTo(pt2.x,pt2.y);
ctx.lineTo(pt3.x,pt3.y);
ctx.closePath();
ctx.stroke();
}
}); // end $(function(){});
< / script>
< / head>
< body>
< canvas id =canvaswidth = 400 height = 400>< / canvas>
< / body>
< / html>
I want to create an interactive digital canvas that will generate a series of near-square polygons in a grid. The below jsFiddle shows a 2x2 grid system of said polygons. If you inspect the code or refresh the page you'll see the center vertex is a semi-randomly generated point that the 4 adjacent polygons share.
I would like to scale this grid to something in the vicinity of 16x16, with each inner vertex being semi-randomly generated, but in its current state the completed code would be inefficient, inflexible, and non-scalable. I know there is a relatively simple solution out there, but considering my inexperience with for loops and arrays, it is currently beyond my scope. Any help is greatly appreciated.
HTML:
<body>
<canvas id="myCanvas" width="200" height="200"></canvas>
</body>
JS:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var randomX = Math.floor((Math.random()-0.5)*30);
var randomY = Math.floor((Math.random()-0.5)*30);
var x1 = canvas.width/2 + randomX;
var x2 = canvas.width;
var y1 = canvas.height/2 + randomY;
var y2 = canvas.height;
//background
context.beginPath();
context.rect(0,0,canvas.height,canvas.width);
context.fillStyle = '#A3DCEE';
context.fill();
//top left polygon
context.beginPath();
context.lineTo(0,0); //top left quadrant
context.lineTo(canvas.width/2,0); //top right quadrant
context.lineTo(x1, y1); //bottom right quadrant
context.lineTo(0, canvas.width/2); //bottom left quadrant
context.closePath();
context.fillStyle = '#ABE2EF';
context.fill();
//top right polygon
context.beginPath();
context.lineTo(x2/2,0); //top left quadrant
context.lineTo(x2,0); //top right quadrant
context.lineTo(x2, y2/2); //bottom right quadrant
context.lineTo(x1, y1); //bottom left quadrant
context.closePath();
context.fillStyle = '#A3DCEE';
context.fill();
//bottom left polygon
context.beginPath();
context.lineTo(0,y2/2); //top left quadrant
context.lineTo(x1,y1); //top right quadrant
context.lineTo(x2/2, y2); //bottom right quadrant
context.lineTo(0, y2); //bottom left quadrant
context.closePath();
context.fillStyle = '#8CD6F6';
context.fill();
//bottom right polygon
context.beginPath();
context.lineTo(x1,y1); //top left quadrant
context.lineTo(x2,y2/2); //top right quadrant
context.lineTo(x2, y2); //bottom right quadrant
context.lineTo(x2/2, y2); //bottom left quadrant
context.closePath();
context.fillStyle = '#85D2ED';
context.fill();
CSS:
html, body {
background-color: #fff;
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
position: relative;
}
canvas {
margin: auto;
position: absolute;
top: 0; left: 0; bottom: 0; right: 0;
}
How to draw a grid with slightly random offset intersection points
Think of each intersecting point on your grid as a circle’s centerpoint.
Then you can calculate an offset from that centerpoint using a random radius and a random angle.
This will randomly offset each intersecting point.
Here’s an example of how to calculate gridpoints with a 0-2.5 pixel "wobble" off it's "usual" position:
// make each grid cell's side 20px
// (you can alter this to fit your needs)
var sideLength=20;
// allow the point to wobble up to 2.5 pixels from its "usual" position
var radius=2.5*Math.random();
// allow that point to wobble at a random angle around its "usual" position
var radianAngle=2*Math.PI*Math.random();
// do the calculation of the new wobbled intersection point
// the x & y are the cell's horizontal(x) and vertical(y) position on the grid
var cx=x*sideLength+radius*Math.cos(radianAngle);
var cy=y*sideLength+radius*Math.sin(radianAngle);
Here is example code and a Fiddle: http://jsfiddle.net/m1erickson/Wqhb9/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
// declare an array
var points=new Array(17);
for(var i=0;i<points.length;i++){
points[i]=new Array(17);
}
var sideLength=20;
// fill the array with
for(var y=0;y<17;y++){
for(var x=0;x<17;x++){
// create a random semi-offset grid point
var radius=2.5*Math.random();
var radianAngle=2*Math.PI*Math.random();
var cx=x*sideLength+radius*Math.cos(radianAngle);
var cy=y*sideLength+radius*Math.sin(radianAngle);
// if this is a sidepoint, don't offset (sides are straight)
if(x==0){cx=0;}
if(y==0){cy=0;}
if(x==16){cx=x*sideLength;}
if(y==16){cy=y*sideLength;}
// add this gridpoint to the points array
points[x][y]={x:cx+10,y:cy+10};
}
}
// stroke the 4 sides of each cell
for(var y=0;y<16;y++){
for(var x=0;x<16;x++){
strokeCell(x,y);
}
}
// draw the 4 sides of the cell
function strokeCell(x,y){
var pt0=points[x][y];
var pt1=points[x+1][y];
var pt2=points[x+1][y+1];
var pt3=points[x][y+1];
ctx.beginPath();
ctx.moveTo(pt0.x,pt0.y);
ctx.lineTo(pt1.x,pt1.y);
ctx.lineTo(pt2.x,pt2.y);
ctx.lineTo(pt3.x,pt3.y);
ctx.closePath();
ctx.stroke();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=400 height=400></canvas>
</body>
</html>
这篇关于使用for循环的可缩放多边形网格的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!