试着画一个书架(可汗学院练习)
Trying to draw a bookshelf (Khan Academy exercise)
我正在做一个基于图书对象数组在画布上绘制书架的练习。具体说明如下:
现在添加更多的书,并使用循环在画布上绘制更多的书架。考虑一下如何使用条件和/或%操作符来做到这一点。
我的代码在循环中包含一个条件,但我似乎不能让它工作。条件在下面代码的最后。
//book array
var books = [{
title: "The Giver",
author: "Lois Lowry",
coverColor: color(214, 255, 219),
stars: 3
}, {
title: "The Outsiders",
author: "S. E. Hinton",
coverColor: color(255, 127, 127),
stars: 5
}, {
title: "Harry Potter",
author: "J. K. Rowling",
coverColor: color(135, 193, 255),
stars: 4
}, {
title: "Harry Potter",
author: "J. K. Rowling",
coverColor: color(135, 193, 255),
stars: 4
}];
// draw shelf
background(230, 187, 122);
fill(173, 117, 33);
rect(0, 120, width, 10);
// book loop
for (var i = 0; i < books.length; i++) {
var book = books[i]; //setting book variable
var xPos = i * 100;
var yPos = 20;
fill(book.coverColor);
rect(xPos + 10, yPos, 90, 100);
fill(0, 0, 0);
textSize(11); //general book drawings
text(book.title, xPos + 15, yPos + 5, 70, 100);
textSize(9);
text(book.author, xPos + 20, yPos * 2, 70, 100);
//Seal of approval
if (book.stars > 3) {
var approvalSeal = getImage("cute/Star");
image(approvalSeal, xPos + 10, yPos * 4, 30, 40);
text("Seal of approval!", xPos + 45, yPos * 4 + 15, 50, 40);
}
//conditional wrap-around
if (xPos > 350) {
xPos = i * 100;
yPos += 120;
}
}
你应该把这个放在循环之外:
var yPos = 20;
当前您在每次迭代中重置yPos
,因此环绕代码永远不会生效。
xPos
也有问题。在每次迭代中将其设置为i * 100
,这将使其超出架子的末端。当你创建一个新的架子时,你必须重置xPos
。
正确的方法是初始化xPos
和yPos
,绘制第一个书架,然后开始迭代这些书。增加图书位置,必要时绕行:
function drawShelf(yPos) {
var saved = context.fillStyle;
fill(color(173, 117, 33));
rect(0, yPos + 120, width, 10);
context.fillStyle = saved;
}
var xPos = 0,
yPos = 0;
drawShelf(yPos);
for (var i = 0; i < books.length; i++) {
var book = books[i];
fill(book.coverColor);
rect(xPos + 10, yPos + 20, 90, 100);
xPos += 100;
if (xPos > 350) {
xPos = 0;
yPos += 130;
drawShelf(yPos);
}
}
您可以在下面的代码片段中看到该代码的运行。我添加了代码来模拟Processing环境中的绘图命令,并且制作了一打带有随机颜色的图书对象。书的其他属性被省略。
var canvas = document.getElementsByTagName('canvas')[0],
width = 410,
height = 400,
context = canvas.getContext('2d');
canvas.width = width;
canvas.height = height;
function background(r, g, b) {
var saved = context.fillStyle;
fill(color(r, g, b));
rect(0, 0, width, height);
context.fillStyle = saved;
}
function color(r, g, b) {
return 'rgb(' + r + ', ' + g + ', ' + b + ')';
}
function fill(style) {
context.fillStyle = style;
}
function rect(x, y, w, h) {
context.fillRect(x, y, w, h);
}
var books = new Array(12);
for (var i = 0; i < books.length; ++i) {
books[i] = {
coverColor: color(
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256),
Math.floor(Math.random() * 256)
)
};
}
background(230, 187, 122);
function drawShelf(yPos) {
var saved = context.fillStyle;
fill(color(173, 117, 33));
rect(0, yPos + 120, width, 10);
context.fillStyle = saved;
}
var xPos = 0,
yPos = 0;
drawShelf(yPos);
for (var i = 0; i < books.length; i++) {
var book = books[i];
fill(book.coverColor);
rect(xPos + 10, yPos + 20, 90, 100);
xPos += 100;
if (xPos > 350) {
xPos = 0;
yPos += 130;
drawShelf(yPos);
}
}
<canvas></canvas>
条件不执行任何操作的原因是因为它位于for循环迭代的末尾。对分配的新值不做任何处理,并且在进行下一次迭代时,坐标将恢复到"第一行图书"坐标。在使用它们之前,您需要分配这些坐标。
我绘制我的(丑陋的)书架的方式是只使用%操作符作为x坐标,并对行进行分层除法。对我来说,这似乎比使用条件句更容易。书架可以看作是一个网格,顺序像
0 1 2
3 4 5
6 7 8 ... etc
因为您写了350
作为限制,我假设您想每行显示3本书。注意x坐标重复出现,像这样
0 100 200
0 100 200
0 100 200
%操作符与正实参一起使用时,返回第一个实参除以第二个实参的余数。使用300作为第二个参数,我得到x坐标的重复序列0、100和200。
现在,行y坐标每3本书增加一次。所以我用数学。floor向下舍入到我想跳转到的确切的整行数,并使用这些值,确定在哪里画这本书。
在我的快速演示中,我只能依赖基本的画布操作。我不熟悉可汗学院提供的工具。
我也不认为你的意思是使用yPos * 2或* 4,因为当你向下移动几行时,这些偏移量会相乘,而不仅仅是向下移动。
var ctx = document.getElementById("canvas").getContext("2d");
function color() {}
function fill(r, g, b) {
}
function rect(x, y, w, h) {
ctx.rect(x, y, w, h);
ctx.stroke();
}
function text(s, x, y, w, h) {
ctx.beginPath();
ctx.moveTo(x, y);
ctx.font = "9px serif";
ctx.fillText(s, x, y + 15);
ctx.stroke();
}
var books = [{
title: "The Giver (0)",
author: "Lois Lowry (0)",
coverColor: color(214, 255, 219),
stars: 3
}, {
title: "The Outsiders (1)",
author: "S. E. Hinton (1)",
coverColor: color(255, 127, 127),
stars: 5
}, {
title: "Harry Potter (2)",
author: "J. K. Rowling (2)",
coverColor: color(135, 193, 255),
stars: 4
}, {
title: "Mary Scooter (3)",
author: "G. Q. Bowling (3)",
coverColor: color(135, 193, 255),
stars: 4
}, {
title: "The Brothers Karmazoov (4)",
author: "F. Downstoveeski (4)",
coverColor: color(214, 255, 219),
stars: 3
}, {
title: "The Unbearable Brightness of Skiing (5)",
author: "Milano Counter (5)",
coverColor: color(255, 127, 127),
stars: 5
}, {
title: "The Uber Gatsby (6)",
author: "Scot-Free Fitzgee (6)",
coverColor: color(135, 193, 255),
stars: 4
}, {
title: "Catch-42 (7)",
author: "Joe Keller (7)",
coverColor: color(135, 193, 255),
stars: 4
}, {
title: "Focker's Pendulum (8)",
author: "Umbrella Ekoh (8)",
coverColor: color(214, 255, 219),
stars: 3
}, {
title: "The Tiny Princess (9)",
author: "Anthony St. Expert (9)",
coverColor: color(255, 127, 127),
stars: 5
}, {
title: "Of Fire and Ice (10)",
author: "George Martinelli (10)",
coverColor: color(135, 193, 255),
stars: 4
}];
// draw shelf
// background(230, 187, 122);
// fill(173, 117, 33);
// rect(0, 120, width, 10);
// book loop
for (var i = 0; i < books.length; i++) {
var book = books[i]; //setting book variable
// DETERMINE WHERE TO PLACE TOP-LEFT BOOK CORNER
var xPos = (i * 100 % 300);
var yPos = 20 + 120 * Math.floor(i / 3);
// var xPos = i*100;
// var yPos = 20;
// fill(book.coverColor);
rect(xPos + 10, yPos, 90, 100);
// fill(0, 0, 0);
// textSize(11);//general book drawings
text(book.title, xPos + 15, yPos + 5, 70, 100);
// textSize(9);
text(book.author, xPos + 20, yPos + 25, 70, 100);
//Seal of approval
if (book.stars > 3) {
// var approvalSeal = getImage("cute/Star");
// image(approvalSeal,xPos+10, yPos*4, 30, 40);
text("Seal of approval!", xPos + 45, yPos + 40 + 15, 50, 40);
}
//conditional wrap-around
// if(xPos > 350) {
// xPos = i*100;
// yPos += 120;
// }
}
<canvas id="canvas" width="450" height="600">
</canvas>
- 创建一个类似链接的按钮,并通过Javascript函数打开一个新的弹出窗口
- jQuery:循环一个具有不同超时值的循环
- 当包含另一个asp文件时,是否也包含所有引用的样式和脚本页面
- 从javascript创建一个列表
- 节点导出返回一个空对象
- 使用clickToggle并在单击另一个元素时关闭元素
- 我可以在json对象中添加一个函数吗
- 使用javascript将动态表从一个html页面打印到另一个html页
- 将jsp文件下拉列表中的选定项分配给一个java变量(比如String selection)
- 表追加而不附加最后一个元素
- 我如何找到一个句子中的所有空格并替换忽略它们
- 雄辩的Javascript:练习:一个列表
- "甚至最后一个“;数组javascript练习
- Javascript练习解决方案.为什么一个比另一个好
- 我正在做一个练习,目标是打印出“史蒂夫”.和“;bill"从代码学院,它只打印一个名字,而不是两个
- 一个案子有多次休息是不是不好的练习
- 试着画一个书架(可汗学院练习)
- 是否有一个独立的JavaScript编译器/解释器与控制台,我可以用它来练习浏览器之外的JavaScript
- 重构/改进一个基本的JavaScript练习——把一个数字分数变成一个字母分数
- 从一个世纪中寻找预期寿命(Eloquent Javascript练习5.3)