我想在画布的右下角绘制几个透视变换的矩形(形状)。为此,我使用了ctx.transform:ctx.transform(1, 0, -1, 1, 10, 10)
。
现在,我想使用变量scale=n
缩放图形的大小,但仍将位置恰好保持在此点(在中心)。
这是我到目前为止编写的代码。移动滑块会更改形状的位置。如何避免这种情况?
let canvas = document.getElementById("canvas")
canvas.width = canvas.height = 200;
$(canvas).appendTo(document.body)
let ctx = canvas.getContext("2d")
let update = function(input) {
let scale = input.value;
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.transform(1, 0, -1, 1, 10, 10)
for (let i = 0; i < 4; i++) {
ctx.fillStyle = (i === 2) ? "#3b2a19" : "#957e67"
let layer = {
x: canvas.width + scale * 7 - i * scale,
y: canvas.height - scale * 5 - i * scale,
width: scale * 3,
height: scale * 1.5
}
ctx.fillRect(layer.x, layer.y, layer.width, layer.height)
ctx.strokeRect(layer.x, layer.y, layer.width, layer.height)
}
ctx.resetTransform();
}
$("input").trigger("input")
#canvas {
border: 2px solid red
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="canvas"></canvas>
<input oninput="update(this)" type="range" min="1" max="20" />
答案 0 :(得分:1)
我建议您自己绘制形状,而不是使用变换。
请参见下面的示例代码:
canvas { border: 1px solid red }
input { position: absolute }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input oninput="update(this)" type="range" min="1" max="20" >
<canvas id="canvas"></canvas>
from StringIO import StringIO
from urllib2 import Request, urlopen
from boto.s3.connection import S3Connection, Bucket, Key
def scrape_to_s3(filename, origin_url):
remote_file = urlopen(Request(origin_url)).read()
memory_file = StringIO(remote_file)
conn = S3Connection(settings.AWS_ACCESS_KEY_ID, settings.AWS_SECRET_ACCESS_KEY)
bucket = conn.get_bucket(settings.AWS_STORAGE_BUCKET_NAME)
k = Key(bucket)
k.key = "media/" + filename
k.set_contents_from_file(memory_file)
答案 1 :(得分:1)
避免在图纸中进行太多计算。
实际上,所有形状都具有相同的恒定宽度和高度,并且相对于堆栈中的前一个形状具有恒定的偏移量。
唯一的真实变量是摄像机的位置。
因此,仅修改此摄像机,并仅更改上下文的变换矩阵即可。
您需要
可以通过一次调用绝对 setTransform 方法来完成前三个步骤。
参数为
setTransform(
scale, // scale-x
0, // skew-x
- scale, // skew-y (we use '- scale' here because skew should be made
// after scale so we need to multiply by scale)
scale, // scale-y
origin_x, // these should be made before so normal scale is ok
origin_y
)
之后,真实的绘图部分将始终相同。
const canvas = document.getElementById("canvas")
canvas.width = canvas.height = 200;
const ctx = canvas.getContext("2d")
const input = document.querySelector('input');
function update() {
// some constants about our shapes
const origin_x = 160; // center of all the rects
const origin_y = 160; // bottom of all the shapes
const w = 33; // width of each rect
const h = 16.5; // height of each rect
const offset = 11; // axis offset (* i)
const scale = input.value;
// first reset the transformation matrix
ctx.setTransform(1,0,0,1,0,0);
// so we clear everything
ctx.clearRect(0, 0, canvas.width, canvas.height)
// now we move our context
// so that our origins are in the top - left
// and that we are already scaled and skewed
ctx.setTransform(scale, 0, -scale, scale, origin_x, origin_y);
// from now on, we don't care about the scale
for (let i = 0; i < 4; i++) {
ctx.fillStyle = (i === 2) ? "#3b2a19" : "#957e67"
let layer = {
x: -i * offset - w/2,
y: -i * offset,
width: w,
height: h
}
ctx.fillRect(layer.x, layer.y, layer.width, layer.height)
ctx.strokeRect(layer.x, layer.y, layer.width, layer.height)
}
}
input.oninput = update;
input.oninput();
#canvas {
border: 2px solid red
}
input {
display: block;
width: 75vw;
}
<input type="range" min="0.01" max="20" value="1" step="0.001" id="inp"/>
<canvas id="canvas"></canvas>