Skip to content Skip to sidebar Skip to footer

Html Canvas & Javascript - Emulating A Scroll-on-hover Event

I am trying to write a scroll-on-hover function in an HTML canvas by defining a hover variable, detecting mouse events over the designated hover area and (on doing so) adding or su

Solution 1:

Animation via animation loops.

You need to have an animation loop that will increment/decrement the value if the conditions are met. This loop can be part of another if you have one (which is better than adding an animation loop for each animated object) or as its own function.

The animation loop does all the rendering, and only if needed (no point rendering something that is already rendered).

Demo

Demo is a copy of the OP's code with modifications to animate the scrolling and give a little user feed back. Though not complete as a scrolling selection box, it will need some tweaking to be useful.

var c = document.getElementById('game'),
canvasX = c.offsetLeft,
canvasY = c.offsetTop,
ctx = c.getContext('2d');

var hover = 0;
const overTypes = {
    lower : 1,
    raise : 2,
    none : 0,
}
var overBox = 0;
var overDist = 0;
const maxSpeed = 4;
const shapeSize = 30;
const hoverScrollSize = 50;
const gradUp = ctx.createLinearGradient(0, 0, 0, hoverScrollSize);
const gradDown = ctx.createLinearGradient(0, ctx.canvas.height - hoverScrollSize, 0, ctx.canvas.height);
gradUp.addColorStop(0, `rgba(${0xA8},${0x4F},${0xB5},1)`);
gradUp.addColorStop(1, `rgba(${0xA8},${0x4F},${0xB5},0)`);
gradDown.addColorStop(1, `rgba(${0xB8},${0x5F},${0xB5},1)`);
gradDown.addColorStop(0, `rgba(${0xB8},${0x5F},${0xB5},0)`);

c.addEventListener('mousemove', mouseMove)
c.addEventListener('mouseout', () => {
    overBox = overTypes.none
}); // stop scroll when mouse out of canvas// start the first framerequestAnimationFrame(() => {
    paint.render(); // paint first framerequestAnimationFrame(mainLoop); // start main loop
});
functionmainLoop() {
    if (overBox !== overTypes.none) {
        hover += overDist / hoverScrollSize * (overBox === overTypes.lower ? maxSpeed : -maxSpeed);
        var bottom =  - (paint.shapes.length - ctx.canvas.height / shapeSize) * shapeSize;

        hover = hover > 0 ? 0 : hover < bottom ? bottom : hover;
        paint.render();
    }
    requestAnimationFrame(mainLoop); // wait for next animation frame
}

functionmouseMove(event) {
    var x = event.clientX - canvasX;
    var y = event.clientY - canvasY;
    if (lowerHoverBoxHitTest(x, y)) {
        overBox = overTypes.lower;
    } elseif (upperHoverBoxHitTest(x, y)) {
        overBox = overTypes.raise;
    } else {
        overBox = overTypes.none;
    }
}

functionupperHoverBoxHitTest(x, y) {
    overDist = hoverScrollSize - y;
    return (x >= 0) && (x <= 350) && (y >= 0) && (y <= hoverScrollSize);
}

functionlowerHoverBoxHitTest(x, y) {
    overDist = y - (ctx.canvas.height - hoverScrollSize);
    return (x >= 0) && (x <= 350) && (y >= ctx.canvas.height - hoverScrollSize) && (y <= ctx.canvas.height);
}

var selectionForMenu = function (id, text, y) {
    this.id = id;
    this.text = text;
    this.y = y;
}

selectionForMenu.prototype.makeSelection = function () {
    ctx.beginPath();
    ctx.fillStyle = '#A84FA5';
    ctx.fillRect(0, this.y + hover, 350, shapeSize)
    ctx.stroke();

    ctx.font = '10px Noto Sans';
    ctx.fillStyle = 'white';
    ctx.textAlign = 'left';
    ctx.fillText(this.text, 10, this.y + hover + 19);
}

varPaint = function (element) {
    this.element = element;
    this.shapes = [];
}

Paint.prototype.addShape = function (shape) {
    this.shapes.push(shape);
}

Paint.prototype.render = function () {
    ctx.clearRect(0, 0, this.element.width, this.element.height);

    for (var i = 0; i < this.shapes.length; i++) {
        this.shapes[i].makeSelection();
    }
    if (overBox !== overTypes.none) {
        ctx.globalAlpha = 0.4 * (overDist / 50);
        ctx.globalCompositeOperation = "lighter";
        if (overBox === overTypes.raise) {
            ctx.fillStyle = gradUp;
            ctx.fillRect(0, 0, ctx.canvas.width, hoverScrollSize);
        } elseif (overBox === overTypes.lower) {
            ctx.fillStyle = gradDown;
            ctx.fillRect(0, ctx.canvas.height - hoverScrollSize, ctx.canvas.width, hoverScrollSize);
        }
        ctx.globalCompositeOperation = "source-over";
        ctx.globalAlpha = 1;
    }
}

var paint = newPaint(c);
for (i = 0; i < 30; i++) {
    paint.addShape(newselectionForMenu(i + 1, i, i * 30));
}

paint.render();
canvas {
  z-index: -1;
  margin: 1em auto;
  border: 1px solid black;
  display: block;
  background: #9F3A9B;
}
<!doctype html><htmllang="en"><head><metacharset="UTF-8"><title>uTalk Demo</title><linkrel='stylesheet'type='text/css'href='wordpractice.css'media='screen'></head><body><canvasid="game"width = "350"height = "150"></canvas></body></html>

Post a Comment for "Html Canvas & Javascript - Emulating A Scroll-on-hover Event"