【问题标题】:Javascript canvas animation using mousedown and mouseup使用 mousedown 和 mouseup 的 Javascript 画布动画
【发布时间】:2021-10-06 08:07:25
【问题描述】:

我有一个带有 88 个钢琴键的 html 表,页面的其余部分是画布。 当用户单击钢琴键时,我正在尝试制作“SeeMusic”动画,即制作一个长度与用户按下鼠标的时间相关的瓷砖。因此有两种可能:

  • Mousedown 处于活动状态:h(图块的高度)每帧增加 2
  • 检测到鼠标上移:h 不再增加,y(图块的 y 位置)每帧增加 2(使其看起来像是在下降)

对于我尝试创建的第一个图块,我的代码就像一个魅力,但问题出现在下一个图块上,它们的速度随着每个图块的创建而增加...有人知道问题出在哪里吗?

const canvas = document.querySelector("canvas"),
ctx = canvas.getContext("2d"),
keys = document.querySelectorAll(".key")
document.querySelector(".keyboard").style.gridTemplateColumns = "repeat("+keys.length+", 1fr)"
canvas.width = window.innerWidth
canvas.height = window.innerHeight*0.8

// Variables
let tile,
particle,
tiles = [],
tileX,
tileWidth = keys[0].offsetWidth

class Tile {
    constructor (x, y, h, dh, dy, c) {
        this.x = x
        this.y = y
        this.h = h
        this.c = c

        this.dh = dh
        this.dy = dy
    }

    Animate() {
        this.h += this.dh
        this.y += this.dy
        window.addEventListener("mouseup", () => {
            this.dh = 0
            this.dy = 2
        })
        this.Draw()
    }

    Draw() {
        ctx.beginPath()
        ctx.fillStyle = this.c
        ctx.fillRect(this.x, this.y, keys[0].offsetWidth, this.h)
        ctx.closePath()
    }
}

function SpawnTile() {
    tiles.push(new Tile(tileX, 0, 0, 2, 0, "red"))
    requestAnimationFrame(Update)
}

function Update() {
    requestAnimationFrame(Update)
    ctx.clearRect(0,0,canvas.width, canvas.height)
    tiles.forEach(tile => {
            tile.Animate()
    })
}

keys.forEach(key => {
    key.addEventListener("mousedown", () => {
        tileX = key.getBoundingClientRect().left
        SpawnTile()
    })
})
*
{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}
body
{
    height: 100vh;
    width: 100vw;
    background-color: white;
}
canvas
{
    display: block;
    margin: auto;
    background-color: black;
    height: 80%;
}
.keyboard
{
    display: grid;
    height: 20%;
    position: relative;
    border-bottom: solid 1px black;
    background: radial-gradient(#fff, rgb(119, 119, 119));
}
.key
{
    width: 100%;
    position: relative;
}
.white {
    background-color: transparent;
    height: 100%;
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
}
.do::before, .fa::before
{
    content: '';
    position: absolute;
    bottom: 0;
    left: 0;
    height: 100%;
    width: 100%;
    background-color: transparent;
    border-left: solid 1px black;
}
.do::after, .fa::after
{
    content: '';
    position: absolute;
    bottom: 0;
    left: 60%;
    height: 35%;
    width: 100%;
    background-color: transparent;
    border-right: solid 1px black;
}
.la::before
{
    content: '';
    position: absolute;
    bottom: 0;
    left: -50%;
    height: 35%;
    width: 100%;
    background-color: transparent;
    border-left: solid 1px black;
}
.la::after
{
    content: '';
    position: absolute;
    bottom: 0;
    left: 30%;
    height: 35%;
    width: 100%;
    background-color: transparent;
    border-right: solid 1px black;
}
.mi::before
{
    content: '';
    position: absolute;
    bottom: 0;
    left: -60%;
    height: 35%;
    width: 100%;
    background-color: transparent;
    border-left: solid 1px black;
}

.black
{
    background-color: rgb(29, 28, 28);
    height: 65%;
    border-bottom-left-radius: 3px;
    border-bottom-right-radius: 3px;
}
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Canvas test</title>
</head>
<body>
    
    <canvas></canvas>
    <div class="keyboard">
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
        <div class="key black reb"></div>
        <div class="key white re"></div>
        <div class="key black mib"></div>
        <div class="key white mi"></div>
        <div class="key white fa"></div>
        <div class="key black solb"></div>
        <div class="key white sol"></div>
        <div class="key black lab"></div>
        <div class="key white la"></div>
        <div class="key black sib"></div>
        <div class="key white si"></div>
        <div class="key white do"></div>
    </div>
    <script src="main.js"></script>
</body>
</html>

【问题讨论】:

    标签: javascript animation canvas mouseevent


    【解决方案1】:

    每次调用SpawnTile 函数时,都会启动新的Update 循环。 它不是那样工作的,所有图块只需要一个动画循环。 您可以在开始时初始化该循环,然后添加样式:

    const canvas = document.querySelector("canvas"),
    ctx = canvas.getContext("2d"),
    keys = document.querySelectorAll(".key")
    document.querySelector(".keyboard").style.gridTemplateColumns = "repeat("+keys.length+", 1fr)"
    canvas.width = window.innerWidth
    canvas.height = window.innerHeight*0.8
    
    // Variables
    let tile,
    particle,
    tiles = [],
    tileX,
    tileWidth = keys[0].offsetWidth
    
    class Tile {
        constructor (x, y, h, dh, dy, c) {
            this.x = x
            this.y = y
            this.h = h
            this.c = c
    
            this.dh = dh
            this.dy = dy
        }
    
        Animate() {
            this.h += this.dh
            this.y += this.dy
            window.addEventListener("mouseup", () => {
                this.dh = 0
                this.dy = 2
            })
            this.Draw()
        }
    
        Draw() {
            ctx.beginPath()
            ctx.fillStyle = this.c
            ctx.fillRect(this.x, this.y, keys[0].offsetWidth, this.h)
            ctx.closePath()
        }
    }
    
    function SpawnTile() {
        // just add tile to array
        tiles.push(new Tile(tileX, 0, 0, 2, 0, "red"))
    }
    
    function Update() {
        requestAnimationFrame(Update)
        ctx.clearRect(0,0,canvas.width, canvas.height)
        tiles.forEach(tile => {
                tile.Animate()
        })
    }
    
    // start update loop one time
    requestAnimationFrame(Update)
    
    keys.forEach(key => {
        key.addEventListener("mousedown", () => {
            tileX = key.getBoundingClientRect().left
            SpawnTile()
        })
    })
    *
    {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
    }
    body
    {
        height: 100vh;
        width: 100vw;
        background-color: white;
    }
    canvas
    {
        display: block;
        margin: auto;
        background-color: black;
        height: 80%;
    }
    .keyboard
    {
        display: grid;
        height: 20%;
        position: relative;
        border-bottom: solid 1px black;
        background: radial-gradient(#fff, rgb(119, 119, 119));
    }
    .key
    {
        width: 100%;
        position: relative;
    }
    .white {
        background-color: transparent;
        height: 100%;
        border-bottom-left-radius: 3px;
        border-bottom-right-radius: 3px;
    }
    .do::before, .fa::before
    {
        content: '';
        position: absolute;
        bottom: 0;
        left: 0;
        height: 100%;
        width: 100%;
        background-color: transparent;
        border-left: solid 1px black;
    }
    .do::after, .fa::after
    {
        content: '';
        position: absolute;
        bottom: 0;
        left: 60%;
        height: 35%;
        width: 100%;
        background-color: transparent;
        border-right: solid 1px black;
    }
    .la::before
    {
        content: '';
        position: absolute;
        bottom: 0;
        left: -50%;
        height: 35%;
        width: 100%;
        background-color: transparent;
        border-left: solid 1px black;
    }
    .la::after
    {
        content: '';
        position: absolute;
        bottom: 0;
        left: 30%;
        height: 35%;
        width: 100%;
        background-color: transparent;
        border-right: solid 1px black;
    }
    .mi::before
    {
        content: '';
        position: absolute;
        bottom: 0;
        left: -60%;
        height: 35%;
        width: 100%;
        background-color: transparent;
        border-left: solid 1px black;
    }
    
    .black
    {
        background-color: rgb(29, 28, 28);
        height: 65%;
        border-bottom-left-radius: 3px;
        border-bottom-right-radius: 3px;
    }
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <link rel="stylesheet" href="style.css">
        <title>Canvas test</title>
    </head>
    <body>
        
        <canvas></canvas>
        <div class="keyboard">
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
            <div class="key black reb"></div>
            <div class="key white re"></div>
            <div class="key black mib"></div>
            <div class="key white mi"></div>
            <div class="key white fa"></div>
            <div class="key black solb"></div>
            <div class="key white sol"></div>
            <div class="key black lab"></div>
            <div class="key white la"></div>
            <div class="key black sib"></div>
            <div class="key white si"></div>
            <div class="key white do"></div>
        </div>
        <script src="main.js"></script>
    </body>
    </html>

    【讨论】:

    • 非常感谢!事实上,我找到了另一种解决方案,但这个更好(可能是因为我的只是隐藏痛苦哈哈)!
    猜你喜欢
    • 1970-01-01
    • 2011-09-24
    • 2011-07-25
    • 1970-01-01
    • 2015-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多