在一般情况下我们可以不设置viewport,这样的话默认的viewport会根据容器自动调整,便于我们按照不同窗口来适配我们的canvas。

    比如我们定义一个相对自适应的元素:

    1. width: 50%;
    2. padding-bottom: 50%;
    3. }

    不设置viewport自动适配容器大小,只会在scene初始化的时候执行,如果我们希望在窗口大小改变的同时保持scene大小继续适配容器大小,那么我们可以将viewport手动设置为['auto', 'auto']

    把viewport设置为['auto', 'auto'],scene会自动注册一个resize事件到window上,当窗口大小改变时,触发viewport的更新。

    1. const scene = new Scene('#coordinate', {viewport: ['auto', 'auto'], resolution: [1540, 600]});
    2. const layer = scene.layer();
    3. const [width] = scene.resolution;
    4. const label = new Label(`resolution: ${[...scene.resolution]} | viewport: ${[...scene.viewport]}`);
    5. label.attr({
    6. anchor: [0.5, 0],
    7. pos: [width / 2, 10],
    8. font: '32px Arial',
    9. fillColor: '#aaa',
    10. });
    11. layer.append(label);
    12. function createBox(x, size) {
    13. const box = new Label(`${size}px`);
    14. const bgcolor = `rgb(${size % 128 + 100}, ${size % 66}, ${size % 77})`;
    15. box.attr({
    16. anchor: [0.5, 0],
    17. pos: [x, 100],
    18. size: [size, size],
    19. bgcolor,
    20. fillColor: '#eee',
    21. font: '24px Arial',
    22. textAlign: 'center',
    23. });
    24. return box;
    25. for(let i = 1, x = 200; i <= 4; i++) {
    26. const box = createBox(x, i * 100);
    27. x += 100 * (i + 1);
    28. layer.append(box);
    29. }
    30. window.addEventListener('resize', () => {
    31. label.text = `resolution: ${[...scene.resolution]} | viewport: ${[...scene.viewport]}`;
    32. });

    有时候,我们需要让canvas的宽度或高度其中一项自适应,但是我们又希望精灵元素保持宽高比例不变,此时我们可以在窗口大小改变的时候同动态修改Scene的resolution属性,一旦它被改变,所有Layer的resolution一同改变,并重新绘制元素。

    坐标 - 图3

    尝试改变窗口大小,可以看到绘制的鹬鸵的大小比例并没有被改变。

    锚点 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:

    1. const scene = new Scene('#anchor', {viewport: ['auto', 'auto'], resolution: [1540, 600]});
    2. const layer = scene.layer();
    3. const box = new Sprite({
    4. anchor: [0.5, 0.5],
    5. size: [200, 200],
    6. pos: [770, 300],
    7. gradients: {
    8. bgcolor: {
    9. vector: [0, 0, 200, 200],
    10. colors: [
    11. {offset: 0, color: 'red'},
    12. {offset: 1, color: 'green'},
    13. ],
    14. },
    15. },
    16. });
    17. layer.append(box);
    18. const cross = new Path('M0 10L20 10M10 0L10 20');
    19. cross.attr({
    20. anchor: [0.5, 0.5],
    21. pos: [770, 300],
    22. strokeColor: 'blue',
    23. });
    24. const label = new Label('anchorX: 0.5, anchorY: 0.5');
    25. label.attr({
    26. pos: [20, 20],
    27. font: '26px Arial',
    28. fillColor: '#aaa',
    29. });
    30. layer.append(label);
    31. box.animate([
    32. {rotate: 0},
    33. {rotate: 360},
    34. ], {
    35. iterations: Infinity,
    36. duration: 3000,
    37. });
    38. const anchorX = document.getElementById('anchorX'),
    39. anchorY = document.getElementById('anchorY');
    40. anchorX.addEventListener('change', (evt) => {
    41. const target = evt.target,
    42. y = box.attr('anchor')[1];
    43. const value = target.value / 100;
    44. box.attr('anchor', [value, y]);
    45. label.text = `anchorX: ${value}, anchorY: ${y}`;
    46. });
    47. anchorY.addEventListener('change', (evt) => {
    48. const target = evt.target,
    49. x = box.attr('anchor')[0];
    50. const value = target.value / 100;
    51. box.attr('anchor', [x, value]);