【问题标题】:Adjust size of drawing canvas with position absolute使用绝对位置调整绘图画布的大小
【发布时间】:2021-03-16 05:18:41
【问题描述】:

我正在尝试制作一个绘图画布。它可以工作,但是当我画画时,线和鼠标不在同一条线上/不同步。这条线离鼠标光标更远。如果我从容器白板中删除 position:relative ,那么它可以正常工作,但问题是,画布填满了整个屏幕,我可以在屏幕上的任何位置绘制。

<div class="container-whiteboard">
    <canvas class="whiteboard" ></canvas>
    <div class="colors">
        <div class="color black"></div>
        <div class="color red"></div>
        <div class="color green"></div>
        <div class="color blue"></div>
        <div class="color yellow"></div>
        <div class="color white"></div>
    </div>
</div>

<style>
.container-whiteboard{
    position: relative;
    width: 100%;
    height: 500px;
    border: 3px solid #73AD21;
}
.whiteboard {
    height: 100%;
    width: 100%;
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    top: 0;
}
.colors {
   position: fixed;
}
</style>
<script>
        var canvas = document.getElementsByClassName('whiteboard')[0];
    var colors = document.getElementsByClassName('color');
    var context = canvas.getContext('2d');

    var current = {
        color: 'black'
    };
    var drawing = false;

    canvas.addEventListener('mousedown', onMouseDown, false);
    canvas.addEventListener('mouseup', onMouseUp, false);
    canvas.addEventListener('mouseout', onMouseUp, false);
    canvas.addEventListener('mousemove', throttle(onMouseMove, 10), false);
    
    //Touch support for mobile devices
    canvas.addEventListener('touchstart', onMouseDown, false);
    canvas.addEventListener('touchend', onMouseUp, false);
    canvas.addEventListener('touchcancel', onMouseUp, false);
    canvas.addEventListener('touchmove', throttle(onMouseMove, 10), false);

    for (var i = 0; i < colors.length; i++){
        colors[i].addEventListener('click', onColorUpdate, false);
    }

    window.addEventListener('resize', onResize, false);
    onResize();

    function drawLine(x0, y0, x1, y1, color, emit){
        context.beginPath();
        context.moveTo(x0, y0);
        context.lineTo(x1, y1);
        context.strokeStyle = color;
        if(color == 'white')
            context.lineWidth = 20;
        else
            context.lineWidth = 2;
        context.stroke();
        context.closePath();

        if (!emit) { return; }
        var w = canvas.width;
        var h = canvas.height;

        channel.whisper('drawingEvent',{
            x0: x0 / w,
            y0: y0 / h,
            x1: x1 / w,
            y1: y1 / h,
            color: color
        })
        console.log('drawing');
    }

    function onMouseDown(e){
        drawing = true;
        current.x = e.clientX||e.touches[0].clientX;
        current.y = e.clientY||e.touches[0].clientY;
    }

    function onMouseUp(e){
        if (!drawing) { return; }
        drawing = false;
        drawLine(current.x, current.y, e.clientX||e.touches[0].clientX, e.clientY||e.touches[0].clientY, current.color, true);
    }

    function onMouseMove(e){
        if (!drawing) { return; }
        drawLine(current.x, current.y, e.clientX||e.touches[0].clientX, e.clientY||e.touches[0].clientY, current.color, true);
        current.x = e.clientX||e.touches[0].clientX;
        current.y = e.clientY||e.touches[0].clientY;
    }

    function onColorUpdate(e){
        current.color = e.target.className.split(' ')[1];
    }

    // limit the number of events per second
    function throttle(callback, delay) {
        var previousCall = new Date().getTime();
        return function() {
        var time = new Date().getTime();

        if ((time - previousCall) >= delay) {
            previousCall = time;
            callback.apply(null, arguments);
        }
        };
    }

    function onDrawingEvent(data){
        console.log(2);
        var w = canvas.width;
        var h = canvas.height;
        drawLine(data.x0 * w, data.y0 * h, data.x1 * w, data.y1 * h, data.color);
    }

    function onResize() {
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;
    }
</script>

【问题讨论】:

  • 通过使.whiteboard absolute100% 宽度和高度,忽略container-whiteboard 的容器,你可以尝试使.whiteboard relative 吗?跨度>
  • 在画布中设置heightwidthrelative 位置
  • 您能否向我们展示您计算光标位置的相关 JavaScript。另外,这既可以在触摸屏上使用,也可以在鼠标上使用?
  • 据我了解,它应该可以正常工作,因为父元素是相对的, position: absolute 不应该忽略容器。尝试删除底部:0;右:0;从白板上。如果你想使用 position: absolute,top 和 left 的 height + width 就足够了。
  • 我也同意 A Haworth 的观点。我们需要更多您的代码。这可能不是 CSS 问题

标签: html css twitter-bootstrap html5-canvas


【解决方案1】:

错位问题是使用clientX/Y获取鼠标位置造成的。

clientX/Y 给出相对于窗口的位置。因此,当您的画布像设置绝对值时那样填充窗口时,窗口内和画布内的位置相同,因此可以正常工作。

但是,当画布相对定位时,画布中的 X/Y 与窗口中的不同。

您需要根据画布坐标进行绘制,因此请改用 event.offsetX/Y。

注意触摸屏的事情有点复杂,因为在 touches 数组中没有 offsetX/Y。相反,您必须进行一些计算

let r = canvas.getBoundingClientRect();
currX = e.touches[0].clientX - r.left;
currY = e.touches[0].clientY - r.top;

查看https://stackoverflow.com/questions/11287877/how-can-i-get-e-offsetx-on-mobile-ipad中的讨论,其中一些不够笼统,但@fiffy 的最新回答应该没问题。

【讨论】:

    猜你喜欢
    • 2021-10-28
    • 2020-12-23
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 2019-01-03
    相关资源
    最近更新 更多