Просмотр исходного кода

janky ellipse draw implemented

miskson 2 лет назад
Родитель
Сommit
c8988dbbfd

+ 0 - 3
hw16-canvas-and-oop/.vscode/settings.json

@@ -1,3 +0,0 @@
-{
-    "liveServer.settings.port": 5501
-}

+ 5 - 3
hw16-canvas-and-oop/index.htm

@@ -8,9 +8,9 @@
         <script src="./eval_files/jquery-3.1.1.min.js"></script>
         <script src="./eval_files/papaparse.min.js"></script>
         <script src="./eval_files/nb.js"></script>
-    </head>
+    <style type="text/css"></style></head>
     <body>
-        <canvas id="canvas" width="400" height="400" style="border: 1px solid black"></canvas> 
+        <canvas id="canvas" width="400" height="400" style="border: 1px dashed black;"></canvas> 
         <button id="undo">UNDO</button>
         <input type="color" id="color">
         <select id="tool">
@@ -18,10 +18,12 @@
             <option value="circle">Circle</option>
             <option value="line">Line</option>
             <option value="rectangle">Rectangle</option>
+            <option value="ellipse">Ellipse</option>
             <option value="select">Select</option>
         </select>
         <input type="number" id="size" value="10">
         <button id="delete">Delete...</button>
-        <script src="./script.js"></script>
+        <script src="./eval_files/index.js"></script>
     
+
 </body></html>

+ 32 - 0
hw16-canvas-and-oop/eval_files/index.css

@@ -0,0 +1,32 @@
+* {
+    box-sizing: border-box;   
+    margin: 0;
+    padding: 0;
+}
+
+body {
+    margin: 0;
+    padding: 0;
+}
+
+ button{
+    width: 100%;
+    font-size: 2em;
+}
+input, button, select{
+    width: 100%;
+    font-size: 2em;
+}
+
+table {
+    border: 1px;
+    border-collapse: collapse;
+}
+
+td,th {
+    border: 1px solid black;
+}
+
+/*div#content {*/
+    /*display: none;*/
+/*}*/

+ 36 - 18
hw16-canvas-and-oop/script.js

@@ -62,6 +62,23 @@ const tools = {
             current = null
         }
     },
+    ellipse: {
+        mousedown(e){
+            current = new Ellipse(e.clientX, e.clientY, 0, 0, color.value, +size.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = e.clientX - current.x
+            current.height = e.clientY - current.y
+
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
     select: {
         click(e){
             console.log(e)
@@ -256,35 +273,36 @@ class Rectangle extends Drawable {
 }
 
 class Ellipse extends Drawable {
-    constructor(x, y, rx, ry, color){
+    constructor(x,y, width, height, color){
         super()
         this.x      = x;
         this.y      = y;
-        this.radius = radius;
+        this.width  = width;
+        this.height = height;
         this.color  = color;
 
         this.draw(); 
     }
+    
 
-    draw(selected){
+    draw(){
         ctx.beginPath();
-        ctx.ellipse(this.x, this.y, this.radius, 0, 2 * Math.PI);
+        ctx.moveTo(this.x, this.y);
+        ctx.lineTo(this.x + this.width, this.y + this.height);
         ctx.closePath();
+        ctx.strokeStyle = this.color;
         ctx.fillStyle = this.color;
-        if (selected){
-            ctx.lineWidth = 2
-            ctx.stroke();
-        }
-        ctx.fill();
-    }
-
-    in(x,y){
-        return this.distanceTo(x,y) < this.radius
-    }
-
-    inBounds(x,y,w,h){ // x = 100, this.x = 102, w = 5
-        return this.x >= x && this.x <= x + w &&
-               this.y >= y && this.y <= y + h 
+        ctx.ellipse(this.x, this.y, this.height, this.width, Math.PI / 2, 0, 2 * Math.PI);
+        // if (selected){
+        //     ctx.beginPath();
+        //     ctx.rect(this.x, this.y, this.width, this.height)
+        //     ctx.lineWidth = 2
+        //     ctx.strokeStyle = 'black'
+        //     ctx.closePath();
+
+        //     ctx.stroke()
+        // }
+        ctx.fill()
     }
 }
 

Разница между файлами не показана из-за своего большого размера
+ 4 - 0
hw16-canvas-and-oop/eval_files/jquery-3.1.1.min.js


+ 305 - 0
hw16-canvas-and-oop/eval_files/nb.js

@@ -0,0 +1,305 @@
+/*
+Copyright 2016-100500 Ivan Grynkin
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), 
+to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, 
+and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
+DEALINGS IN THE SOFTWARE. 
+*/
+
+function nbInit(a,b){
+    var root=document, $s=a;
+
+    var dom = null;
+    var closure = null;
+
+    function searchElement(root, selector){
+        if ((selector.indexOf('|dom') === selector.length - 4) && (selector.length > 4)){
+            selector = selector.slice(0,selector.length - 4)
+            dom      = true;
+        }
+        if ((selector.indexOf('|closure') === selector.length - 8) && (selector.length > 8)){
+            selector = selector.slice(0,selector.length - 8)
+            closure  = true;
+        }
+        if (root === document){
+            var items = [root.getElementById(selector)]; 
+        }
+        else {
+            items = root.querySelectorAll("#" + selector); 
+        }
+        items     = items[0]     ? items :  root.querySelectorAll(selector);
+        items     = items.length ? items :  root === document ? root.getElementsByName(selector) : root.querySelectorAll("[name='" + selector + "']"); 
+        items     = items.length ? items :  root.getElementsByClassName(selector); 
+        return items;
+    }
+
+    if (a instanceof HTMLElement){
+        root = a;
+        $s   = b;
+    }
+    else if (typeof a === "string"){
+        root = searchElement(document, a)[0];
+        $s   = b;
+    }
+    if (b instanceof HTMLElement){
+        root = b;
+    }
+    else if (typeof b === "string"){
+        root = searchElement(document, a)[0];
+    }
+    if (typeof $s === "undefined"){
+        $s = {}
+    }
+
+    function nBind(callback, prop, direction){
+        direction = direction || "write";
+        for (var selector in $s){
+            var result = [];
+            selector = prop || selector; //change selector to passed if it
+
+            var items = searchElement(root, selector);
+            for (var i=0,item=items[i];i<items.length;i++,item=items[i]){
+                if (direction == "write" &&  Array.isArray($s[selector]) && (item.children.length == 0 || (items.length == $s[selector].length && items.length > 1))){
+                    if (closure){
+                        callback(item, $s, selector, $s[selector]);
+                    }
+                    else {
+                        callback(item, $s, selector, $s[selector][i]);
+                    }
+                }
+                else {
+                    var res = callback(item, $s, selector);
+                    if (typeof res !== "undefined"){
+                        result.push(res)
+                    }
+                }
+            }
+
+            
+            $s[selector] = result.length ? (result.length == 1 ? result[0] : result) : $s[selector];
+
+            if (prop) return;  //exit if selector passed, no iteration
+        }
+    }
+
+    function recursiveObjectSet(item, value){
+        if (typeof item === 'undefined'){
+            return;
+        }
+        for (var key in value){
+            if (typeof value[key] !== 'object'){
+                item[key] = value[key];
+            }
+            else {
+                recursiveObjectSet(item[key], value[key]);
+            }
+        }
+    }
+
+    function syncToDOM(prop){
+        nBind(function (item, $s, selector, value, key, thisByClass){
+            value = typeof value === 'undefined' ? $s[selector] : value;
+            var keyExists = typeof key !== 'undefined';
+            if (closure){
+                item.nbData = value[0].apply(item, value.slice(1))
+                return;
+            }
+            if ((!item.children.length && !Array.isArray(value) && typeof value === 'object') || thisByClass || dom){ //hash array on single leaf node -> set attrs on the tag
+                recursiveObjectSet(item,value);
+                if (!thisByClass && !dom){
+                    item.nbData = value;
+                }
+                return;
+            }
+            if (keyExists && "value" in item){ //if hash key-value pair. Usable for select > option
+                item.value = key;
+            }
+            if (typeof value === "boolean" && item.type !== 'checkbox'){ //boolean means visibility, except checkbox
+                if (value){
+                    item.style.display = "originalDisplay" in item ? item.originalDisplay : "";
+                }
+                else {
+                    item.originalDisplay = "originalDisplay" in item ? item.originalDisplay : item.style.display;
+                    item.style.display   = "none";
+                }
+                return;
+            }
+            if (item.type === 'radio' && !keyExists){ //radiogroup set
+                if (item.value === value){ //only item with right value to set
+                    item.checked = true;
+                }
+                return;
+            }
+            if (item.type === 'checkbox' && !keyExists){ //checkbox setting by boolean
+                item.checked = !!value;
+                return;
+            }
+            if (item.children.length && typeof value === "object"){ //recursive fill
+                item.copy = item.copy || item.cloneNode(true); //original node
+                item.nbData = value;
+                var originalChildren = item.copy.children;
+                var i = 0;
+                var isArray = Array.isArray(value);      //different logic for array and objects
+                if (!isArray){ // if first key in array find as class name in one of subnodes
+                    var classFound = false;
+                    for (var key in value){
+                        if (item.getElementsByClassName(key).length){
+                            classFound = true;
+                            break;
+                        }
+                    }
+                    if (classFound){
+                        for (var key in value){
+                            var classSubnodes = item.getElementsByClassName(key);
+                            for (var i=0;i<classSubnodes.length;i++){
+                                arguments.callee(classSubnodes[i], $s, selector, value[key]); // recursively fill subnode with that data. No reason to pass a key, because key are class selector, not value for option
+                            }
+                            if (item.classList.contains(key)){
+                                arguments.callee(item, $s, selector, value[key], undefined, true); // recursively fill subnode with that data. No reason to pass a key, because key are class selector, not value for option
+                            }
+                        }
+                        return;
+                    }
+                }
+                item.innerHTML = "";                     //remove sub nodes
+                for (var key in value){ //otherwise iterate over array or object
+                    var newNode = originalChildren[i].cloneNode(true);
+                    item.appendChild(newNode);
+                    if (isArray){
+                        arguments.callee(newNode, $s, selector, value[key]);
+                    }
+                    else {
+                        arguments.callee(newNode, $s, selector, value[key], key);
+                    }
+                    i = (i +1) % originalChildren.length;
+                }
+                return;
+            }
+            if (!keyExists){ //default logic: set text or value to data value
+                item[("value" in item) && item.tagName !== 'LI' ? "value" : "innerText"] = value;
+            }
+            else {
+                item.innerText = value; // do not try to overwrite value on option nodes
+            }
+        },prop, "write");
+    }
+
+    function syncFromDOM(prop){
+        nBind(function(item, $s, selector){
+            if (closure){
+                return item.nbData()
+            }
+            if (item.type === 'radio'){
+                if (item.checked) 
+                    return item.value; 
+                return;
+            }
+            if (item.type === 'checkbox'){
+                return item.checked;
+            }
+            if (item.tagName === 'SELECT'){
+                return item.value;
+            }
+            if ("nbData" in item){
+                var value = item.nbData;
+                var isArray = Array.isArray(value);      //different logic for array and objects
+                if (item.children.length && typeof value === "object"){ //recursive fill
+                    if (!isArray){ // if first key in array find as class name in one of subnodes
+                        var classFound = false;
+                        for (var key in value){
+                            if (item.getElementsByClassName(key).length){
+                                classFound = true;
+                                break;
+                            }
+                        }
+                        if (classFound){
+                            for (var key in value){
+                                var classSubnodes = item.getElementsByClassName(key);
+                                for (var i=0;i<classSubnodes.length;i++){
+                                    value[key] = arguments.callee(classSubnodes[i], $s, selector); // recursively fill subnode with that data. No reason to pass a key, because key are class selector, not value for option
+                                }
+                            }
+                            return value;
+                        }
+                    }
+                    else{
+                        value.length = 0;
+                        for (var key=0;key<item.children.length;key++){ //otherwise iterate over array or object
+                            value[key] = arguments.callee(item.children[key], $s, selector);
+                        }
+                        return value;
+                    }
+                    //else {
+                        //for (var key in value){
+                            //value[key] = arguments.callee(item.children[key], $s, selector);
+                        //}
+                    //}
+                }
+                if (!isArray && typeof value === 'object' && item.children.length === 0){ //hash array on single leaf node -> set attrs on the tag
+                    for (var key in value){
+                        value[key] = item[key];
+                    }
+                    return value;
+                }
+                if (!isArray && typeof value === 'object'){ //hash array on single leaf node -> set attrs on the tag
+                    value = {};
+                    for (var i=0;i<item.children.length;i++){
+                        var childItem = item.children[i];
+                        value[childItem.value] = childItem.innerText;
+                    }
+                    return value;
+                }
+            }
+            if ("value" in item){
+                return item.value;
+            }
+            return item.innerText; 
+        },prop, "read");
+    }
+
+    syncToDOM();
+
+    var scopeProxy = new Proxy($s,{
+        get(target, prop){
+            //if (!(prop in target) && (document.getElementById(prop) || 
+                                      //document.querySelectorAll(prop).length || 
+                                      //document.getElementsByName(prop).length ||
+                                      //document.getElementsByClassName(prop).length)){
+                target[prop] = null;
+            //}
+            syncFromDOM(prop);
+            dom = null;
+            closure = null;
+            return target[prop];
+        },
+        set(target, prop, value){
+            //syncFromDOM();
+            target[prop] = value
+            syncToDOM(prop);
+            dom = null;
+            closure = null;
+            return true;
+        },
+    })
+
+    return scopeProxy;
+}
+
+function nbGetData(el){
+    while (!('nbData' in el)){
+        if (el.parentElement){
+            el = el.parentElement;
+        }
+        else {
+            return null;
+        }
+    }
+    return el.nbData;
+}

Разница между файлами не показана из-за своего большого размера
+ 6 - 0
hw16-canvas-and-oop/eval_files/papaparse.min.js