>  기사  >  웹 프론트엔드  >  HTML5를 사용하여 Windows와 유사한 그리기 소프트웨어를 만드는 방법

HTML5를 사용하여 Windows와 유사한 그리기 소프트웨어를 만드는 방법

一个新手
一个新手원래의
2017-10-19 09:56:212081검색

아직 이 그리기 도구를 완성하지 못했지만 일반적인 구조와 일반적인 간단한 그래픽 그리기 기능을 구현했습니다.

1. 직선, 원, 직사각형 및 정다각형을 그릴 수 있습니다. [완료]

2. 및 획 색상 선택 [완료]

3, 획 및 채우기 기능 선택 [완료]

후속 버전:

지우개, 좌표계, 선 설정, 화살표, 기타 프로세스 그래픽, 자르기 및 조정 그래픽. . . . .

궁극적 목표:

프로세스 드로잉 소프트웨어

전에 친구가 내 블로그에 메시지를 남기는 것을 보고 다음과 같이 말했습니다.

이 친구에게 정말 감사합니다. 마침내 시간을 내서 매우, 매우 오늘 작은 프로토타입!

완전한 프로토타입 코드를 직접 열어서 로컬 테스트에 복사해 주세요.


<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>windows简易画图工具 - by ghostwu</title>
</head>

<body>
    <div class="paint">
        <div class="paint-header">
            <ul>
                <li class="active">形状</li>
                <li>颜色</li>
                <li>绘制类型</li>
                <li>线条宽度</li>
                <li>橡皮擦</li>
            </ul>
        </div>
        <div class="paint-body">
            <div class="siderbar">
                <div class="item active" data-type="paint-shape">
                    <ul>
                        <li class="active" data-role="line">线条</li>
                        <li data-role="circle">圆形</li>
                        <li data-role="rect">矩形</li>
                        <li data-role="polygon">正多边形</li>
                        <li data-role="arrow">箭头</li>
                    </ul>
                </div>
                <div class="item" data-type="paint-color">
                    <ul>
                        <li data-role="strokeStyle">
                            <input type="color" data-role="strokeStyle">
                        </li>
                        <li data-role="fillStyle">
                            <input type="color" data-role="fillStyle">
                        </li>
                    </ul>
                </div>
                <div class="item" data-type="paint-type">
                    <ul>
                        <li data-role="stroke">描边</li>
                        <li data-role="fill">填充</li>
                    </ul>
                </div>
                <div class="item" data-type="paint-line">
                    <ul>
                        <li data-role="1">小号</li>
                        <li data-role="4">中号</li>
                        <li data-role="7">大号</li>
                        <li>
                            <input type="number" data-role="line-size" placeholder="请输入数字">
                        </li>
                    </ul>
                </div>
                <div class="item" data-type="paint-erase">
                    <ul>
                        <li>
                            <input type="number" data-role="erase-size" placeholder="请输入数字">
                        </li>
                    </ul>
                </div>
            </div>
        </div>
    </div>
    <script>// <![CDATA[
        var oPaintBody = document.querySelector( &#39;.paint-body&#39; );
        var oC = document.createElement( &#39;canvas&#39; );
        oC.setAttribute( &#39;width&#39;, &#39;830&#39; );
        oC.setAttribute( &#39;height&#39;, &#39;500&#39; );
        oPaintBody.appendChild( oC );
        var aHeaderLi = document.querySelectorAll(&#39;.paint-header li&#39;),
            aItem = document.querySelectorAll(&#39;.paint-body .item&#39;),
            oCanvas = document.querySelector(&#39;.paint canvas&#39;),
            oGc = oCanvas.getContext(&#39;2d&#39;),
            cWidth = oCanvas.width, cHeight = oCanvas.height,
            curItem = aItem[0],
            aItemLi = curItem.querySelectorAll(&#39;li&#39;);

        for (let i = 0, len = aHeaderLi.length; i < len; i++) { //头部选项卡切换功能
            aHeaderLi[i].onclick = function () {
                for (let j = 0; j < len; j++) {
                    aHeaderLi[j].classList.remove(&#39;active&#39;);
                    aItem[j].style.display = &#39;none&#39;;
                }
                aItem[i].style.display = "block";
                this.classList.add(&#39;active&#39;);
                curItem = aItem[i];
                aItemLi = curItem.querySelectorAll(&#39;li&#39;);
                activeItem(aItemLi);
            }
        }
        activeItem(aItemLi);
        var role = null;
        function activeItem(aItemLi) { //canvas左侧选项卡切换功能
            for (let i = 0, len = aItemLi.length; i < len; i++) {
                aItemLi[i].onclick = function () {
                    checkPaintType(this); //绘制类型
                    for (let j = 0; j < len; j++) {
                        aItemLi[j].classList.remove(&#39;active&#39;);
                    }
                    this.classList.add(&#39;active&#39;);
                }
            }
        }

        function Shape(canvasObj, cxtObj, w, h) {
            this.oCanvas = canvasObj;
            this.oGc = cxtObj;
            this.oCanvas.width = w;
            this.oCanvas.height = h;
            this.fillStyle = &#39;#000&#39;;
            this.storkeStyle = &#39;#000&#39;;
            this.lineWidth = 1;
            this.drawType = &#39;line&#39;;
            this.paintType = &#39;stroke&#39;;
            this.nums = 6; //正多边形的边数
        }

        Shape.prototype = {
            init: function () {
                this.oGc.fillStyle = this.fillStyle;
                this.oGc.strokeStyle = this.strokeStyle;
                this.oGc.lineWidth = this.lineWidth;
            },
            draw: function () {
                var _this = this;
                this.oCanvas.onmousedown = function (ev) {
                    _this.init();
                    var oEvent = ev || event,
                        startX = oEvent.clientX - _this.oCanvas.offsetLeft,
                        startY = oEvent.clientY - _this.oCanvas.offsetTop;
                    _this.oCanvas.onmousemove = function (ev) {
                        _this.oGc.clearRect(0, 0, _this.oCanvas.width, _this.oCanvas.height);
                        var oEvent = ev || event,
                            endX = oEvent.clientX - _this.oCanvas.offsetLeft,
                            endY = oEvent.clientY - _this.oCanvas.offsetTop;
                        _this[_this.drawType](startX, startY, endX, endY);
                    };
                    _this.oCanvas.onmouseup = function () {
                        _this.oCanvas.onmousemove = null;
                        _this.oCanvas.onmouseup = null;
                    }
                }
            },
            line: function (x1, y1, x2, y2) {
                this.oGc.beginPath();
                this.oGc.moveTo(x1, y1);
                this.oGc.lineTo(x2, y2);
                this.oGc.closePath();
                this.oGc.stroke();
            },
            circle: function (x1, y1, x2, y2) {
                this.oGc.beginPath();
                var r = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
                this.oGc.arc(x1, y1, r, 0, 2 * Math.PI, false);
                this.oGc.closePath();
                this.oGc[this.paintType]();
            },
            rect: function (x1, y1, x2, y2) {
                this.oGc.beginPath();
                this.oGc.rect(x1, y1, x2 - x1, y2 - y1);
                this.oGc[this.paintType]();
            },
            polygon: function (x1, y1, x2, y2) {
                var angle = 360 / this.nums * Math.PI / 180;//边对应的角的弧度
                var r = Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
                this.oGc.beginPath();
                for (var i = 0; i < this.nums; i++) {
                    this.oGc.lineTo(x1 + r * Math.cos(angle * i), y1 + r * Math.sin(angle * i));
                }
                this.oGc.closePath();
                this.oGc[this.paintType]();
            }
        }

        var oShape = new Shape(oCanvas, oGc, cWidth, cHeight);
        function checkPaintType(liType) {
            var dataType = liType.parentNode.parentNode.dataset.type;
            var curType = liType.dataset.role;
            switch (dataType) {
                case &#39;paint-shape&#39;: //形状
                    oShape.drawType = curType;
                    if (curType == &#39;polygon&#39;) {
                        oShape.nums = prompt("请输入边数", 6);
                    }
                    oShape.draw();
                    break;
                case &#39;paint-color&#39;: //绘制颜色
                    liType.children[0].onchange = function () {
                        oShape[this.dataset.role] = this.value;
                    }
                    oShape.draw();
                    break;
                case &#39;paint-type&#39;: //绘制类型
                    oShape.paintType = curType;
                    oShape.draw();
                    break;
            }
        }
// ]]></script>
    <style>
        .paint * {
            margin: 0;
            padding: 0;
        }

        .paint ul,
        .paint li {
            list-style: none;
        }

        .paint li:hover {
            cursor: pointer;
        }

        .paint {
            width: 980px;
            margin: 20px auto;
            border: 1px solid #ccc;
            overflow: hidden;
        }

        .paint .paint-header ul {
            width: 980px;
            height: 40px;
            line-height: 40px;
            border-bottom: 1px solid #ccc;
        }

        .paint .paint-header li {
            float: left;
            width: 120px;
            height: 40px;
            line-height: 40px;
            text-align: center;
        }

        .paint li.active {
            box-shadow: #666 0px 1px 8px inset;
        }

        .paint .paint-body .siderbar {
            float: left;
            width: 150px;
            height: 500px;
        }

        .paint .paint-body .item {
            width: 150px;
            overflow: hidden;
            display: none;
            height: 500px;
            border-right: 1px solid #ccc;
        }

        .paint .paint-body canvas {
            float: right;
        }

        .paint .paint-body .item li {
            height: 40px;
            text-align: center;
            border-bottom: 1px solid #ccc;
            line-height: 40px;
        }

        .paint .paint-body .active {
            display: block;
        }
    </style>
</body>

프로세스 설계에 관해서는 나중에 할 기능, 아이디어는 기본적으로 있습니다. 나침반이 여기 있어요, 갖고 싶어요 이 궁극적인 목표를 달성하려면 그리기 도구를 완성하여 목표에 가까워야 합니다. 현재의 간단한 기능을 먼저 경험해 보겠습니다. 아래에서 정상적으로 그림을 그릴 수 있습니다. [캔버스를 지원하려면 브라우저가 필요합니다]
주로 대상의 프로토타입 아키텍처에 대해 이야기하겠습니다.

1, 그래픽 그리기 부분을 캡슐화합니다. it 생성된 클래스 Shape

function Shape(canvasObj, cxtObj, w, h) {
        this.oCanvas = canvasObj;
        this.oGc = cxtObj;
        this.oCanvas.width = w;
        this.oCanvas.height = h;
        this.fillStyle = &#39;#000&#39;;
        this.storkeStyle = &#39;#000&#39;;
        this.lineWidth = 1;
        this.drawType = &#39;line&#39;;
        this.paintType = &#39;stroke&#39;;
        this.nums = 6; //正多边形的边数
    }

canvasObj: 캔버스 캔버스 객체입니다

cxtObj: 컨텍스트 그리기 환경입니다

w: 캔버스 너비

h: 캔버스 높이

fillStyle: 채우기 color

StrokeStyle: 획 color

lineWidth: 선 너비

drawType: 기본값은 직선을 그리는 것입니다.

paintType: 두 가지 옵션(획/채우기)

2, 프로토타입 객체에 대한 공용 메서드 그리기 확장 그래픽 그리기

그리기 메서드는 주로 시작점 좌표(startX, startY)와 끝점 좌표(endX, endY)를 가져옵니다.

그런 다음 특정 그래픽을 그리려면 init 메서드를 호출합니다. 다음 주요 메소드에 대해:

_this[_this.drawType](startX, startY, endX, endY)

이 메소드의 drawType은 다음과 같이 인터페이스의 실시간 선택에 따라 해당 그리기 유형을 변경합니다.

_this['line']( startX, startY, endX, endY)

oShape 객체의 선이라고 불리는 것은 직선을 그리는 방법

Shape.prototype = {
        init: function () {
            this.oGc.fillStyle = this.fillStyle;
            this.oGc.strokeStyle = this.strokeStyle;
            this.oGc.lineWidth = this.lineWidth;
        },
        draw: function () {
            var _this = this;
            this.oCanvas.onmousedown = function ( ev ) {
                _this.init();
                var oEvent = ev || event,
                    startX = oEvent.clientX - _this.oCanvas.offsetLeft,
                    startY = oEvent.clientY - _this.oCanvas.offsetTop;
                _this.oCanvas.onmousemove = function ( ev ) {
                    _this.oGc.clearRect( 0, 0, _this.oCanvas.width, _this.oCanvas.height );
                    var oEvent = ev || event,
                        endX = oEvent.clientX - _this.oCanvas.offsetLeft,
                        endY = oEvent.clientY - _this.oCanvas.offsetTop;
                    _this[_this.drawType](startX, startY, endX, endY);
                };
                _this.oCanvas.onmouseup = function(){
                    _this.oCanvas.onmousemove = null;
                    _this.oCanvas.onmouseup = null;
                }
            }
        },
        line: function ( x1, y1, x2, y2 ) {
            this.oGc.beginPath();
            this.oGc.moveTo( x1, y1 );
            this.oGc.lineTo( x2, y2 );
            this.oGc.closePath();
            this.oGc.stroke();
        },
        circle : function( x1, y1, x2, y2 ){
            this.oGc.beginPath();
            var r = Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) );
            this.oGc.arc( x1, y1, r, 0, 2 * Math.PI, false );
            this.oGc.closePath();
            this.oGc[this.paintType]();
        },
        rect : function( x1, y1, x2, y2 ){
            this.oGc.beginPath();
            this.oGc.rect( x1, y1, x2 - x1, y2 - y1 );
            this.oGc[this.paintType]();
        },
        polygon : function( x1, y1, x2, y2 ){
            var angle = 360 / this.nums * Math.PI / 180;//边对应的角的弧度
            var r = Math.sqrt( Math.pow( x2 - x1, 2 ) + Math.pow( y2 - y1, 2 ) );
            this.oGc.beginPath();
            for( var i = 0; i < this.nums; i ++ ){
                this.oGc.lineTo( x1 + r * Math.cos( angle * i ), y1 + r * Math.sin( angle * i ) );
            }
            this.oGc.closePath();
            this.oGc[this.paintType]();
        }
    }

3 인터페이스 조작은 기본적으로 매우 간단합니다. 탭의 동작 + html5의 커스텀 속성 + classList의 적용

위 내용은 HTML5를 사용하여 Windows와 유사한 그리기 소프트웨어를 만드는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.