- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我有一个 Canvas 元素。它根据 art vanishing points 绘制了一些线条.
我正在尝试从一个消失点绘制房子(目前它只是一个盒子)。框的大小由 delta
变量决定。如果我手动更改值,它会这样做:
我想要一个 slider 来改变 delta
变量。但是我得到了一些非常奇怪的效果。也就是说,线条是在框架外向右绘制的。我到处都转储了 console.log 语句,但我仍然找不到问题(甚至如何调试 Canvas 问题?)
var canvas = document.querySelector("canvas");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas.width = 1600;
canvas.height = 800;
var ct = canvas.getContext("2d");
// TODO
// 1. Make a center point
// 2. Draw lines jutting from center
// 3. Draw a line parallel to canvas bottom
// 4. Draw an adjoining item upward
// x, y
// right, down
// Nomenclature
// x0a
// coordinate type, vanishingPt#, endPtName
// Vanishing point 0
var x0 = 400;
var y0 = 400;
// Vanishing point end 0a
var x0a = 0;
var y0a = 2 * y0;
// Vanishing point end 0b
var x0b = 2 * x0;
var y0b = 2 * y0;
// Define delta
var delta = 700;
function init() {
console.log(delta, "delta");
console.log(x0b, "x0b");
console.log(y0b, "y0b");
console.log(x0, "x0");
console.log(y0, "y0");
// First Line
ct.beginPath();
ct.moveTo(x0, y0);
ct.lineTo(x0a, y0a);
ct.strokeStyle = 'red';
ct.stroke();
// Second Line
ct.beginPath();
ct.moveTo(x0, y0);
ct.lineTo(x0b, x0b);
ct.strokeStyle = 'green';
ct.stroke();
// House based on second Line
ct.beginPath();
ct.moveTo(x0b, y0b); // starting point
ct.lineTo(x0b + delta, y0b); // right x+100
ct.lineTo(x0b + delta, y0b - delta); // up y-100
ct.lineTo(x0b, y0b - delta); // left x-100
ct.lineTo(x0b, y0b); // down y+100
ct.lineTo(x0b, y0b - delta); // back up y-100
//calculate
ct.lineTo(x0, y0);
ct.lineTo(x0b + delta, y0b - delta);
ct.strokeStyle = 'blue';
ct.stroke();
}
init();
var slider = document.getElementById("myRange");
slider.oninput = function () {
delta = this.value;
requestAnimationFrame(init()); // redraw everything
}
body {
background-color: lightgray;
display: flex;
justify-content: center;
align-items: center;
}
.slideContainer {
position: fixed;
right: 30px;
top: 30px;
background-color: lightblue;
z-index: 20;
}
canvas {
border: 1px dotted red;
padding: 80px;
background-color: lightgray;
transform: scale(0.5);
}
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="wrapper">
<div class="slideContainer">
<input type="range" min="1" max="800" value="50" class="slider" id="myRange">
</div>
<canvas id="canvas"></canvas>
</div>
<script src="script.js"></script>
</body>
</html>
最佳答案
您的问题已得到回答,但您的问题有一些不好的做法需要指出,否则它们会被复制。
oninput
是鼠标移动驱动的事件。切勿从任何由鼠标移动事件引起的事件中调用渲染函数或 requestAnimationFrame
。许多设备上的鼠标移动事件可以以比显示速率高得多的速率触发(高达每秒 1000 次)。显示器每 60 秒只能显示 1 帧,画得再多就看不到了,而且会耗尽客户的电池。
如果您从鼠标驱动的输入事件中调用 requestAnimationFrame
,您最终会将许多渲染排队等待下一次显示刷新,并且当 requestAnimationFrame
尝试平衡负载时,它可能会为下一帧排队渲染,因此最新更新可能最多延迟 2 个显示帧。大多数帧将永远不会被看到,你仍然在消耗能量。
使用信号量和标准渲染循环来监控信号量并仅在需要时重绘,并且每帧仅重绘一次。 (见示例)
除非您将 Canvas 转换为动画的一部分,否则不要通过 CSS 规则 transform: scale(0.5);
(或任何其他缩放方法)缩小 Canvas 其次,如果您将显示 Canvas 的大小减半,这意味着您需要渲染 4 倍的像素,并使用 4 倍的内存。
您可以通过 Canvas 2D API 进行缩放,这样做可以节省客户端电池生命周期并提高性能。
我已经完全重写了代码,希望它能有所帮助。两个要点,Updates,Scale 都注释掉了。添加代码以使用点而不是 x,y 坐标,因为我很懒。
requestAnimationFrame(update); // start anim loop
const ctx = canvas.getContext("2d");
const width = 1600; // The ideal resolution
const height = 800; // used to scale content
canvas.width = innerWidth;
canvas.height = innerHeight;
//Scales 2D context to always show the ideal resolution area
const scaleToFit = () => { // sets canvas scale to fit content
var scale = Math.min(canvas.width / width, canvas.height / height);
ctx.setTransform(scale, 0, 0, scale, 0, 0);
}
var redraw = true; // when true scene is redrawn ready for the next display refresh
// Working with points is easier
const point = (x = 0, y = 0) => ({x, y});
const pointCpy = (p, x = 0, y = 0) => ({x: p.x + x, y: p.y + y});
const scalePoint = (origin, point, scale) => {
point.x = (point.x - origin.x) * scale + origin.x;
point.y = (point.y - origin.y) * scale + origin.y;
};
const p1 = point(400,400);
const pA = point(p1.x, p1.y * 2);
const pB = point(p1.x * 2, p1.y * 2);
var delta = 50;
// the slider input event should not directly trigger a render
slider.addEventListener("input",(e) => {
delta = Number(e.target.value);
redraw = true; // use a semaphore to indicate content needs to redraw.
});
function update() { // this is the render loop it only draws when redraw is true
if (redraw) { // monitor semaphore
redraw = false; // clear semaphore
ctx.setTransform(1,0,0,1,0,0); // resets transform
ctx.clearRect(0,0,ctx.canvas.width, ctx.canvas.height);
scaleToFit();
draw();
}
requestAnimationFrame(update);
}
// this was your function init()
function draw() {
drawLine(p1, pA, "red");
drawLine(p1, pB, "green");
drawVBox(pB, delta, p1, "blue");
}
function drawVBox(p, size, vp, col, width) { // p is bottom left vp is vanish point
ctx.strokeStyle = col;
ctx.lineWidth = width;
const p0 = pointCpy(p); // get corners
const p1 = pointCpy(p, size);
const p2 = pointCpy(p, size, -size);
const p3 = pointCpy(p, 0, -size);
drawPoly(col, width, p0, p1, p2, p3)
ctx.beginPath(); // draw vanish lines
pathLine(p0, vp);
pathLine(p1, vp);
pathLine(p2, vp);
pathLine(p3, vp);
ctx.stroke();
const scale = 1 - size / (800 * 2);
scalePoint(vp, p0, scale);
scalePoint(vp, p1, scale);
scalePoint(vp, p2, scale);
scalePoint(vp, p3, scale);
drawPoly(col, width, p0, p1, p2, p3);
}
// Use function to do common tasks and save your self a lot of typing
function drawLine(p1, p2, col, width = 1) {
ctx.strokeStyle = col;
ctx.lineWidth = width;
ctx.beginPath();
ctx.lineTo(p1.x, p1.y); // First point after beginPath can be lineTo
ctx.lineTo(p2.x, p2.y);
ctx.stroke();
}
function drawPoly(col,width, ...points) {
ctx.strokeStyle = col;
ctx.lineWidth = width;
ctx.beginPath();
for(const p of points){
ctx.lineTo(p.x, p.y); // First point after beginPath can be lineTo
}
ctx.closePath(); // draw closing line
ctx.stroke();
}
function pathLine(p1, p2) {
ctx.moveTo(p1.x, p1.y);
ctx.lineTo(p2.x, p2.y);
}
canvas {
position : absolute;
top: 0px;
left: 0px;
background-color: lightgray;
z-index: -20;
}
<canvas id="canvas"></canvas>
<input type="range" min="1" max="800" value="50" id="slider">
<code id="info"></code>
关于javascript - Canvas 请求动画在 slider 输入到 javascript 变量时超出帧,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53464401/
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: How to nest OR statements in JavaScript? 有没有办法做到这一点:
在 JavaScript 中有没有办法让一个变量总是等于一个变量?喜欢var1 = var2但是当var2更新,也是var1 . 例子 var var1 = document.getElementBy
我正在努力理解这代表什么 var1 = var2 == var3 我的猜测是这等同于: if (var2 == var3): var1 = var2 最佳答案 赋值 var1 = var2
这个问题已经有答案了: What does the PHP error message "Notice: Use of undefined constant" mean? (2 个回答) 已关闭 8
我在临时表中有几条记录,我想从每条记录中获取一个值并将其添加到一个变量中,例如 color | caption -------------------------------- re
如何将字符串转为变量(字符串变量--> $variable)? 或者用逗号分隔的变量列表然后转换为实际变量。 我有 2 个文件: 列名文件 行文件 我需要根据字符串匹配行文件中的整行,并根据列名文件命
我有一个我无法解决的基本 php 问题,我也想了解为什么! $upperValueCB = 10; $passNodeMatrixSource = 'CB'; $topValue= '$uppe
这可能吗? php $variable = $variable1 || $variable2? 如果 $variable1 为空则使用 $variable2 是否存在类似的东西? 最佳答案 PHP 5
在 Perl 5.20 中,for 循环似乎能够修改模块作用域的变量,但不能修改父作用域中的词法变量。 #!/usr/bin/env perl use strict; use warnings; ou
为什么这不起作用: var variable; variable = variable.concat(variable2); $('#lunk').append(variable) 我无法弄清楚这一点
根据我的理解,在32位机器上,指针的sizeof是32位(4字节),而在64位机器上,它是8字节。无论它们指向什么数据类型,它们都有固定的大小。我的计算机在 64 位上运行,但是当我打印包含 * 的大
例如: int a = 10; a += 1.5; 这运行得很完美,但是 a = a+1.5; 此作业表示类型不匹配:无法从 double 转换为 int。所以我的问题是:+= 运算符 和= 运算符
您好,我写了这个 MySQL 存储过程,但我一直收到这个语法错误 #1064 - You have an error in your SQL syntax; check the manual that
我试图在我的场景中显示特定的奖牌,这取决于你的高分是基于关卡的目标。 // Get Medal Colour if levelHighscore goalScore { sc
我必须维护相当古老的 Visual C++ 源代码的大型代码库。我发现代码如下: bIsOk = !!m_ptr->isOpen(some Parameters) bIsOk的数据类型是bool,is
我有一个从 MySQL 数据库中提取的动态产品列表。在 list 上有一个立即联系 按钮,我正在使用一个 jquery Modal 脚本,它会弹出一个表单。 我的问题是尝试将产品信息变量传递给该弹出窗
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
jQuery Core Style Guidelines建议两种不同的方法来检查变量是否已定义。 全局变量:typeof variable === "undefined" 局部变量:variable
这个问题已经有答案了: 已关闭11 年前。 Possible Duplicate: “Variable” Variables in Javascript? 我想肯定有一种方法可以在 JavaScrip
在语句中使用多重赋值有什么优点或缺点吗?在简单的例子中 var1 = var2 = true; 赋值是从右到左的(我相信 C# 中的所有赋值都是如此,而且可能是 Java,尽管我没有检查后者)。但是,
我是一名优秀的程序员,十分优秀!