zoukankan      html  css  js  c++  java
  • Canvas学习系列二:Canvas的坐标系统

    上一章内容中我们对canvas元素有了一个初步的认识,在接下来的章节中我们会慢慢学习canvas中图形的绘制;但是在绘制之前我们先来看看canvas中的坐标系统,因为这样我们才能知道绘制的图形放在什么位置。

    比如:我们要在canvas画布的(100,100)这个位置绘制一个圆

    看到这个要求顿时就懵逼了,(100, 100)在什么地方!!!

    至于为什么会懵逼呢?是因为我们不知道canvas的坐标系统,那么我们就赶紧来了解Canvas中的坐标系统吧

    在了解canvas坐标系统之前,我们先来看看其他的坐标系统

    窗口坐标系统

    窗口坐标是我们在Web页面中用到的坐标系统,与我们数学中的直角坐标系统有所不同;

    通常窗口坐标系统的原点在屏幕(一般指浏览器)的左上角

    直角坐标系统: 直角坐标系统中原点沿x轴向右方向为正值,反之为负值;原点沿y轴向上方向为正值,反之为负值。

    窗口坐标系统: 窗口坐标系统与直角坐标系统都含有x轴,y轴,两轴的交点为坐标原点(0,0),原点沿x轴向右方向为正值,不同的是原点沿y轴方向向下为正值。

    当然窗口坐标系统也是负值的,只是有些时候会跑到屏幕范围之外,另我们没有看到。

    Canvas坐标系统

    在canvas绘图环境对象中有一个与2d绘图环境对应的3d绘图环境,叫做WebGL,所以canvas坐标系统中包含3D绘图环境,不过我们现在只说2D绘图环境。

    在2D绘图环境中的坐标系统,默认情况下是与窗口坐标系统相同,它以canvas的左上角为坐标原点,沿x轴向右为正值,沿y轴向下为正值。其中canvas坐标的单位都是 "px"。

    然而Canvas的坐标系并不是固定的,我们可以对坐标系统进行评议放缩及旋转,我们成为坐标变换

    • 平移:(translate)
    • 缩放:(scale)
    • 旋转:(rotate)
    • 自定义变换方式

    坐标系统的变换是Canvas中非常基本的功能,在这里我们不做过多的阐述,后面我们会详细讲解坐标系统的变换。

    窗口坐标换为canvas坐标

    HTML5应用程序是以事件来驱动的,浏览器通过事件对象传递给监听器的坐标是窗口坐标,开发者需要知道发生事件的点相对于canvas的位置,而不是相对于浏览器中的位置,所以必须进行转换

    转换方法1:

    //坐标转换
        function windowToCanvas(canvas, x,  y){
            var canvasBox = canvas.getBoundingClientRect(); //获取canvas元素的边界框
            return {
                x: (x - canvasBox.left)*(canvas.width/canvasBox.width), //对canvas元素大小与绘图表面大小不一致时进行缩放
                y: (y - canvasBox.top)*(canvas.height/canvasBox.height)
            }
        }

    转换方法2:利用 scrollLeft, clientLeft, offsetLeft属性

    function windowToCanvas2(canvas, x, y){
            return {
                x: x + document.body.scrollLeft - document.body.clientLeft - canvas.offsetLeft,
                y: y + document.body.scrollTop - document.body.clientTop - canvas.offsetTop
            }
        }

    利用上述所说窗口坐标转换canvas坐标的方法,我们可以绘制一个鼠标辅助线的例子;

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            body {
                 100%;
                height: 100%;
                display: flex;
                justify-content: center;
                align-items: flex-start;
            }
            #canvas {
                border: 1px solid darkorange;
            }
        </style>
    </head>
    <body>
    <canvas id="canvas" width="600" height="300"></canvas>
    <script type="text/javascript">
        window.addEventListener('load', loadCanvas);
        function loadCanvas(){
            var canvas = document.getElementById('canvas');
            if(!canvas.getContext){
                return;
            }
            var context = canvas.getContext('2d');
            //添加鼠标移动事件
            canvas.addEventListener('mousemove', MouseMove);
    
            function MouseMove(e){
                var location = windowToCanvas2(canvas, e.clientX, e.clientY);
                drawLines(location.x, location.y);
            }
    
            //绘制辅助线
            function drawLines(x, y){
                context.clearRect(0, 0, context.canvas.width, context.canvas.height);
                context.beginPath();
                context.moveTo(x, 0);
                context.lineTo(x, context.canvas.height);
                context.stroke();
                context.beginPath();
                context.moveTo(0, y);
                context.lineTo(context.canvas.width, y);
                context.stroke();
                context.font = '20pt Arial';
                context.fillStyle = 'green';
                var text = '(' + parseInt(x)+','+parseInt(y) + ')';
                context.fillText(text, 20, 50);
            }
        }
    
        //坐标转换
        function windowToCanvas(canvas, x,  y){
            var canvasBox = canvas.getBoundingClientRect(); //获取canvas元素的边界框
            return {
                x: (x - canvasBox.left)*(canvas.width/canvasBox.width), //对canvas元素大小与绘图表面大小不一致时进行缩放
                y: (y - canvasBox.top)*(canvas.height/canvasBox.height)
            }
        }
      //方法2 function windowToCanvas2(canvas, x, y){
    return { x: x + document.body.scrollLeft - document.body.clientLeft - canvas.offsetLeft, y: y + document.body.scrollTop - document.body.clientTop - canvas.offsetTop } } </script> </body> </html>

    canvas绘制一个简单的坐标轴

    虽然我们还没有学习canvas中图行的绘制,这里只是简单的展示一个例子。后面我们会慢慢学习canvas中图形的绘制,你就觉得绘制会如此的简单。

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>坐标轴</title>
        <style>
            html, body {
                margin: 0;
                padding: 0;
            }
            #canvas {
                margin: 100px;
            }
        </style>
    </head>
    <body>
    <canvas id="canvas"></canvas>
    <script type="text/javascript">
        window.onload = function(){
            var canvas = document.getElementById('canvas');
            canvas.width = '400';
            canvas.height = '300';
            if(!canvas.getContext){
                alert('当前浏览器不支持canvas');
                return;
            }
            var context = canvas.getContext('2d');
            context.translate(50,20);
            //绘制坐标轴的方法
            function drawAxis(cxt){
                var dx = 0,
                    dy = 0,
                    x = 0,
                    y = 0,
                    w = canvas.width,
                    h = canvas.height;
                cxt.lineWidth = 2;
                cxt.strokeStyle = "green";
    
                var textX = 0;
                var textY = 0;
                //绘制x轴
                cxt.moveTo(x, y);
                cxt.lineTo(w, y);
                cxt.stroke();
                //绘制数字
                while (dx < w) {
                    cxt.font = '12pt Arial';
                    cxt.fillStyle = 'red';
                    cxt.fillText(textY, dx, 0);
                    textY+= 50;
                    dx+=50;
                }
    
                //绘制y轴
                cxt.moveTo(x, y);
                cxt.lineTo(x, h);
                cxt.stroke();
    
                //绘制数字
                while (dy < h) {
                    cxt.font = '12pt Arial';
                    cxt.fillStyle = 'red';
                    cxt.fillText(textX, -30, dy);
                    textX+= 50;
                    dy+=50;
                }
    
            }
            drawAxis(context);
        };
    </script>
    </body>
    </html>

    总结:

    在我们绘制图形之前,必须要搞清楚canvas的坐标系统,这样才能知道我们具体要在哪里绘制图形。

    canvas的2D环境绘图坐标系统,原点(0,0)位于canvas元素的左上角顶点处,沿x轴向右为正值,沿y轴向下为正值,与我们数学中的直角坐标系是不同的,但是与我们的窗口坐标系(web页面的坐标)是相同的

    canvas的坐标系统不是一直不变的,我们可以通过坐标变换来改变,后面章节我们会单独说到。

    对canvas绘制图形感兴趣的同学,请持续关注后续更新,如有不对的地方也请指出并多多交流。

  • 相关阅读:
    客户端回传事件接口IPostBackEventHandler
    《敏捷无敌》—— 一本非常好看的“IT技术言情小说”
    面向对象之设计
    Zac谈网络编辑需要注意的SEO技巧
    面向对象之领悟
    《网络营销实战密码》推荐
    设计模式建造者模式(builder)
    设计模式工厂方法(FactoryMethod)
    struts1.x与struts2的比较表
    设计模式原型模式(ProtoType)
  • 原文地址:https://www.cnblogs.com/beevesnoodles/p/6994963.html
Copyright © 2011-2022 走看看