在一般情况下我们可以不设置viewport,这样的话默认的viewport会根据容器自动调整,便于我们按照不同窗口来适配我们的canvas。
比如我们定义一个相对自适应的元素:
width: 50%;
padding-bottom: 50%;
}
不设置viewport自动适配容器大小,只会在scene初始化的时候执行,如果我们希望在窗口大小改变的同时保持scene大小继续适配容器大小,那么我们可以将viewport手动设置为['auto', 'auto']
。
把viewport设置为['auto', 'auto']
,scene会自动注册一个resize
事件到window上,当窗口大小改变时,触发viewport的更新。
const scene = new Scene('#coordinate', {viewport: ['auto', 'auto'], resolution: [1540, 600]});
const layer = scene.layer();
const [width] = scene.resolution;
const label = new Label(`resolution: ${[...scene.resolution]} | viewport: ${[...scene.viewport]}`);
label.attr({
anchor: [0.5, 0],
pos: [width / 2, 10],
font: '32px Arial',
fillColor: '#aaa',
});
layer.append(label);
function createBox(x, size) {
const box = new Label(`${size}px`);
const bgcolor = `rgb(${size % 128 + 100}, ${size % 66}, ${size % 77})`;
box.attr({
anchor: [0.5, 0],
pos: [x, 100],
size: [size, size],
bgcolor,
fillColor: '#eee',
font: '24px Arial',
textAlign: 'center',
});
return box;
for(let i = 1, x = 200; i <= 4; i++) {
const box = createBox(x, i * 100);
x += 100 * (i + 1);
layer.append(box);
}
window.addEventListener('resize', () => {
label.text = `resolution: ${[...scene.resolution]} | viewport: ${[...scene.viewport]}`;
});
有时候,我们需要让canvas的宽度或高度其中一项自适应,但是我们又希望精灵元素保持宽高比例不变,此时我们可以在窗口大小改变的时候同动态修改Scene的resolution属性,一旦它被改变,所有Layer的resolution一同改变,并重新绘制元素。
尝试改变窗口大小,可以看到绘制的鹬鸵的大小比例并没有被改变。
锚点 anchor
在前面的例子中,我们看到Sprite元素有不同的定位方式,具体表现为不同的anchor值。比如例1是anchor:[0.5, 0.5]
,例2是anchor:[0.5, 0]
,例3没有设定,是默认值anchor:[0, 0]
。
在spritejs中,元素的anchor属性用来表示它的参考点,坐标定位、transform都是根据anchor值来设定的,默认值为[0, 0],即以元素的左上角位置为参考点,正常值取0~1之间,表示参考点坐标相对于元素宽高的比例,因此如果设置为[1, 1]则为右下角。
调整anchor值,看看元素有什么变化:
anchor-x: anchor-y:
const scene = new Scene('#anchor', {viewport: ['auto', 'auto'], resolution: [1540, 600]});
const layer = scene.layer();
const box = new Sprite({
anchor: [0.5, 0.5],
size: [200, 200],
pos: [770, 300],
gradients: {
bgcolor: {
vector: [0, 0, 200, 200],
colors: [
{offset: 0, color: 'red'},
{offset: 1, color: 'green'},
],
},
},
});
layer.append(box);
const cross = new Path('M0 10L20 10M10 0L10 20');
cross.attr({
anchor: [0.5, 0.5],
pos: [770, 300],
strokeColor: 'blue',
});
const label = new Label('anchorX: 0.5, anchorY: 0.5');
label.attr({
pos: [20, 20],
font: '26px Arial',
fillColor: '#aaa',
});
layer.append(label);
box.animate([
{rotate: 0},
{rotate: 360},
], {
iterations: Infinity,
duration: 3000,
});
const anchorX = document.getElementById('anchorX'),
anchorY = document.getElementById('anchorY');
anchorX.addEventListener('change', (evt) => {
const target = evt.target,
y = box.attr('anchor')[1];
const value = target.value / 100;
box.attr('anchor', [value, y]);
label.text = `anchorX: ${value}, anchorY: ${y}`;
});
anchorY.addEventListener('change', (evt) => {
const target = evt.target,
x = box.attr('anchor')[0];
const value = target.value / 100;
box.attr('anchor', [x, value]);