Explorar el Código

HWJS19 (Canvas) done

DimaBondarenko hace 3 años
padre
commit
12a376d504
Se han modificado 5 ficheros con 394 adiciones y 0 borrados
  1. 2 0
      HWJS19/css/style.min.css
  2. 9 0
      HWJS19/css/style.min.css.map
  3. 29 0
      HWJS19/index.html
  4. 322 0
      HWJS19/js/script.js
  5. 32 0
      HWJS19/sass/style.scss

+ 2 - 0
HWJS19/css/style.min.css

@@ -0,0 +1,2 @@
+*{-webkit-box-sizing:border-box;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}
+/*# sourceMappingURL=style.min.css.map */

+ 9 - 0
HWJS19/css/style.min.css.map

@@ -0,0 +1,9 @@
+{
+    "version": 3,
+    "mappings": "AAAA,AAAA,CAAC,AAAC,CACE,UAAU,CAAE,UAAU,CACtB,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACb,AAED,AAAA,IAAI,AAAC,CACD,MAAM,CAAE,CAAC,CACT,OAAO,CAAE,CAAC,CACb,AAEA,AAAA,MAAM,AAAA,CACH,KAAK,CAAE,IAAI,CACX,SAAS,CAAE,GAAG,CACjB,AACD,AAAA,KAAK,CAAE,MAAM,CAAE,MAAM,AAAA,CACjB,KAAK,CAAE,IAAI,CACX,SAAS,CAAE,GAAG,CACjB,AAED,AAAA,KAAK,AAAC,CACF,MAAM,CAAE,GAAG,CACX,eAAe,CAAE,QAAQ,CAC5B,AAED,AAAA,EAAE,CAAC,EAAE,AAAC,CACF,MAAM,CAAE,eAAe,CAC1B",
+    "sources": [
+        "../sass/style.scss"
+    ],
+    "names": [],
+    "file": "style.min.css"
+}

+ 29 - 0
HWJS19/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="css/style.min.css">
+    <script src="https://code.jquery.com/jquery-3.1.1.min.js"></script>
+    <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/4.1.3/papaparse.min.js"></script>
+    <script src="http://gitlab.a-level.com.ua/gitgod/nanobind/raw/master/static/nb.js"></script>
+    <title>Document</title>
+</head>
+<body>
+        <canvas id='canvas' width=400 height=400></canvas> 
+        <button id='undo'>UNDO</button>
+        <input type='color' id='color'>
+        <select id='tool'>
+            <option value='ellipse'>Ellipse</option>
+            <option value='line'>Line</option>
+            <option value='rectangle'>Rectangle</option>
+            <option value='graffity'>Graffity</option>
+            <option value='circle'>Circle</option>
+            <option value='select'>Select</option>
+        </select>
+        <input type='number' id='size' value=10>
+        <button id='delete'>Delete...</button>
+    <script src="js/script.js"></script>
+</body>
+</html>

+ 322 - 0
HWJS19/js/script.js

@@ -0,0 +1,322 @@
+const canvas = document.getElementById('canvas')
+const ctx    = canvas.getContext('2d')
+
+const width  = canvas.width;
+const height = canvas.height;
+
+let current;
+let selection = []
+
+const tools = {
+    graffity: {
+        mousemove(e){ //e.buttons 0b00000x11 & 0b00000100 == x
+            (e.buttons & 0b001) && new Circle(e.layerX, e.layerY, +size.value, color.value)
+        }
+    },
+    ellipse: {
+        mousedown(e){
+            current = new Ellipse(e.layerX, e.layerY, 0, 0, color.value, +size.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = (e.layerX - current.x)     
+            current.height = (e.layerY - current.y)
+            
+
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    circle: {
+        mousedown(e){
+            current = new Circle(e.layerX,e.layerY, 10, color.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.radius = current.distanceTo(e.layerX, e.layerY)
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    line: { //ctrl-c ctrl-v в rectangle. Так же добавьте его в <select id='tool'>
+        mousedown(e){
+            current = new Line(e.layerX, e.layerY, 0, 0, color.value, +size.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = e.layerX - current.x
+            current.height = e.layerY - current.y
+            
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    rectangle: { //ctrl-c ctrl-v в rectangle. Так же добавьте его в <select id='tool'>
+        mousedown(e){
+            current = new Rectangle(e.layerX, e.layerY, 0, 0, color.value, +size.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = e.layerX - current.x
+            current.height = e.layerY - current.y
+
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    select: {
+        click(e){
+            console.log(e)
+            let found = Drawable.instances.filter(c => c.in && c.in(e.layerX, e.layerY))
+            if (found.length){
+                if (e.ctrlKey){
+                    selection.push(found.pop())
+                }
+                else {
+                    selection = [found.pop()]
+                }
+            }
+            else {
+                if (!e.ctrlKey) selection = []
+            }
+
+            console.log('selection', selection)
+
+            Drawable.drawAll(selection)
+        },
+        mousedown(e){
+            //
+        },
+        mousemove(e){
+
+        },
+
+        mouseup(e){
+            //x,y, w, h прямоугольника
+            //selection - только те элеменеты Drawable.instances которые в границах прямоугольника.
+        },
+    }
+}
+
+function superHandler(evt){
+    let t = tools[tool.value]
+    if (typeof t[evt.type] === 'function')
+        t[evt.type].call(this, evt)
+}
+
+canvas.onmousemove = superHandler
+canvas.onmouseup   = superHandler
+canvas.onmousedown = superHandler
+canvas.onclick = superHandler
+
+function Drawable(){
+   Drawable.addInstance(this);   
+}
+
+const distance = (x1,y1, x2, y2) => ((x1-x2)**2 + (y1-y2)**2)**0.5
+
+Drawable.prototype.draw = function(){};
+Drawable.prototype.distanceTo = function(x,y){
+    if (typeof this.x !== 'number' ||
+        typeof this.y !== 'number'){
+        return NaN
+    }
+    return distance(this.x, this.y, x, y)
+};
+Drawable.instances = [];
+Drawable.addInstance = function(item){
+    Drawable.instances.push(item);
+}
+
+Drawable.drawAll = function(selection=[]){
+    ctx.clearRect(0,0,width,height);
+    Drawable.forAll(item => item.draw())
+    selection.forEach(item  => item.draw(true))
+}
+
+Drawable.forAll = function(callback){
+    for(var i = 0; i<Drawable.instances.length;i++){
+        callback(Drawable.instances[i])
+    }
+}
+
+class Circle extends Drawable {
+    constructor(x,y,radius, color){
+        super()
+        this.x      = x;
+        this.y      = y;
+        this.radius = radius;
+        this.color  = color;
+
+        this.draw(); 
+    }
+
+    draw(selected){
+        ctx.beginPath();
+        ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI);
+        ctx.closePath();
+        ctx.fillStyle = this.color;
+        if (selected){
+            ctx.strokeStyle = "red";
+            ctx.lineWidth = 5
+            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 
+    }
+}
+
+
+class Line extends Drawable { //смочь скопировать в Rectangle и поменять отприсовку
+    constructor(x,y, width, height, color, lineWidth){
+        super()
+        this.x      = x;
+        this.y      = y;
+        this.width  = width;
+        this.height = height;
+        this.color  = color;
+        this.lineWidth  = lineWidth;
+        this.draw(); 
+    }
+    
+
+    draw(selected){
+        ctx.beginPath();
+        ctx.moveTo(this.x, this.y);
+        ctx.lineTo(this.x + this.width, this.y + this.height);
+        ctx.closePath();
+        ctx.strokeStyle = this.color;
+        ctx.lineWidth   = this.lineWidth
+        ctx.stroke();
+    }
+
+    in(x, y){
+        
+        let lineAngle = Math.atan2(this.width, this.height) ;
+        let mouseAngle = Math.atan2(x - this.x, y - this.y) ;
+        let mouseLength = (((x - this.x)**2)+((y - this.y)**2))**0.5;
+        let lineLength = (((this.width)**2)+((this.height)**2))**0.5;
+        let angle =  mouseAngle - lineAngle;
+        let newX = Math.cos(angle) * mouseLength;
+        let newY = Math.sin(angle) * mouseLength;
+        return newX >= 0 && newX <= lineLength && (newY <= this.lineWidth/2 && newY >= (-this.lineWidth/2))
+    }
+} 
+
+class Rectangle extends Drawable { //смочь скопировать в Rectangle и поменять отрисовку
+    constructor(x,y, width, height, color, lineWidth){
+        super()
+        this.x      = x;
+        this.y      = y;
+        this.width  = width;
+        this.height = height;
+        this.color  = color;
+        this.lineWidth  = lineWidth;
+        this.draw(); 
+    }
+
+    draw(selected){
+        ctx.beginPath();
+        ctx.rect(this.x,this.y,this.width,this.height);
+        ctx.fillStyle = this.color;
+        ctx.fill();
+        
+        if(selected){
+            ctx.strokeStyle = "red";
+            ctx.lineWidth = 5
+            ctx.stroke();
+        }
+   
+    }
+    //поменять метод draw шоб рисовал прямоугольник
+    in(x,y){
+        return this.x < x && x < this.x + this.width && this.y < y && y < this.y + this.height
+    }
+}
+//Ellipse по аналогии
+//
+class Ellipse extends Drawable { //смочь скопировать в Ellipse и поменять отрисовку
+    //поменять метод draw шоб рисовал ellipse
+    constructor(x,y, width, height, color, lineWidth){
+        super()
+        this.x      = x;
+        this.y      = y;
+        this.width  = width;
+        this.height = height;
+        this.color  = color;
+        this.lineWidth  = lineWidth;
+        this.draw(); 
+    }
+
+    get rx(){
+        return this.width/2
+    }
+
+    get ry(){
+        return this.height/2
+    }
+
+    get h(){
+        return this.x + this.width/2
+    }
+
+    get k(){
+        return this.y + this.height/2
+    }
+
+    draw(selected){
+        ctx.beginPath();
+        ctx.ellipse(this.h, this.k, this.rx, this.ry, 0, 0, 2 * Math.PI);
+        ctx.closePath()
+        ctx.stroke();
+        ctx.fillStyle = this.color;
+        ctx.fill();
+        if(selected){
+            ctx.strokeStyle = "red";
+            ctx.lineWidth = 5
+            ctx.stroke();
+        }
+        
+   
+    }
+    in(x,y){
+        console.log(this.x, this.y)
+        return  ((((x - this.h)**2)/this.rx**2) + (((y - this.k)**2)/this.ry**2)) <=1
+    }
+}
+
+color.onchange = () => {
+    selection.forEach(c => c.color = color.value)
+    Drawable.drawAll(selection)
+}
+
+document.getElementById('delete').onclick = () =>{
+    Drawable.instances = Drawable.instances.filter(item => !selection.includes(item))
+    selection = []
+    Drawable.drawAll()
+}
+

+ 32 - 0
HWJS19/sass/style.scss

@@ -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;*/
+/*}*/