2 - 显示对象, 容器


先做一个简单的绘制: 预载9张图标, 把每个图标按次序排列在 3x3 的空间内。代码如下:

var canvas = document.querySelector('#myCanvas')
canvas.width = window.innerWidth
canvas.height = window.innerHeight
var ctx = canvas.getContext('2d')

function preload (list) {
    var loaded = 0
    var total = list.length
    for (var i = 0; i < total; i++) {
        var img = new Image()
        img.src = list[i]
        imgList.push(img)
        img.onload = (e) => {
            loaded ++
            if(loaded == total){
                start()
            }
        }
    }
}

var preloadList = [
    '/static/icon_1.png',
    '/static/icon_2.png',
    '/static/icon_3.png',
    '/static/icon_4.png',
    '/static/icon_5.png',
    '/static/icon_6.png',
    '/static/icon_7.png',
    '/static/icon_8.png',
    '/static/icon_9.png',
    '/static/icon_10.png'
]
var imgList = []

preload(preloadList)

function start() {
    imgList.forEach((img, index) => {
            var row = index % 3
            var col = Math.floor(index / 3)
            ctx.drawImage(img, row * 100, col * 100)
        })
}

效果如图:

如果只是静态的绘制, 这样完全没有问题。但是如果需要对特定的图标做单独的调整, 因为画布是一个整体, 也并没有记住单独某个图标的状态, 可能需要擦除整个画布, 再重新绘制每个元素, 并且对想要调整位置的图标单独处理

现在把画布作为一个 “容器”(Container). 容器内的每一个独立的视图部分, 称之为 “显示对象”(DisplayObject); 它们每个都有各自的坐标(x, y); 它们都是这个容器的”子元素”(children)。

当我们需要改变画布内容时, 找到想要改变的那个显示对象, 读取并修改相关属性, 最后刷新容器即可

代码如下:

function start() {
    imgList.forEach((img, index) => {
        var row = index % 3
        var col = Math.floor(index / 3)
        var bitmap = new DisplayObject(img)
        bitmap.x = row * 100
        bitmap.y = col * 100
        children.push(bitmap)
    })

    updateView()
}

//  子显示对象合集
var children = []
//  更新视图的方法
function updateView () {
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    children.forEach((child) => {
        child.draw()
    })
}

//  显示对象构造方法
var DisplayObject = function (img) {
    this.img = img
    this.x = 0
    this.y = 0

    this.draw = function () {
        ctx.drawImage(this.img, this.x, this.y)
    }
}

在以上的代码中, 9个图标由 9个 DisplayObject 所持有; 只需要改变某个显示对象的相关属性, 并最终刷新视图(updateView), 即可更新画布内容。