THE SKRIBBLE SHAPES TOOL (10+ FEATURES)

45° SNAP, RECTANGLE, BEZIER, CIRCLE, RHOMBUS, GRID, MORE

目前為 2022-01-07 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        THE SKRIBBLE SHAPES TOOL (10+ FEATURES)
// @namespace   https://greasyfork.org/users/861129
// @match       *://skribbl.io/*
// @grant       none
// @version     0.6.1
// @license	MIT
// @copyright   2022, smartboyprofesor (https://greasyfork.org/users/861129)
// @author      smartboyprofesor
// @description 45° SNAP, RECTANGLE, BEZIER, CIRCLE, RHOMBUS, GRID, MORE
// ==/UserScript==
/* jshint esversion: 6 */

const canvas = document.querySelector('#canvasGame');
const lineCanvas = document.createElement('canvas');
const linectx = lineCanvas.getContext('2d');

lineCanvas.oncontextmenu = () => { return false; };
[lineCanvas.width, lineCanvas.height] = [canvas.width, canvas.height];
canvas.parentElement.insertBefore(lineCanvas, canvas);

lineCanvas.setAttribute('style', `
	position: absolute;
	cursor: crosshair;
	width: 100%;
	user-select: none;
	z-index: 2;
	filter: opacity(0.1);
	display: none;`
                       );

lineCanvas.clear = () => {
    linectx.clearRect(0, 0, lineCanvas.width, lineCanvas.height);
};

let icon=document.getElementsByClassName("logoSmall");for(let i=0;i<icon.length;i++)icon[i].remove()
let screengame = document.getElementById("screenGame")
let toolbar2 = document.createElement("div")
screengame.appendChild(toolbar2)
toolbar2.style="height:48px;border-radius:2px;display:flex;margin-top:65px;justify-content:center;background-image:linear-gradient(to bottom, #ffffff 0%,#f3f3f3 50%,#ededed 51%,#ffffff 100%)"

function createtbdiv(){
    let div = document.createElement("div")
    toolbar2.appendChild(div)
    div.style="height:75%;width:1px;background:rgba(51,51,51,.5);margin:0px 5px;top:25%;transform:translateY(25%)"
}

let labelstyle = "margin-left:5px;margin-right:5px;text-align:center"
let inputstyle = "border-radius:5px;text-align:center;color:#bd2057;width:150px"
let buttonstyle = "cursor:pointer;border-radius:5px;margin-top:5px;margin-bottom:5px;background-image:linear-gradient(to bottom, #bfd255 0%,#8eb92a 50%,#72aa00 51%,#9ecb2d 100%);color:white;font-weight:bolder;margin-left:5px;margin-right:5px"
let horigridlabel = document.createElement("label")
horigridlabel.innerHTML="Horizontal Lines"
toolbar2.appendChild(horigridlabel)
horigridlabel.style=labelstyle
let vertgridlabel = document.createElement("label")
vertgridlabel.innerHTML="Vertical Lines"
toolbar2.appendChild(vertgridlabel)
vertgridlabel.style=labelstyle
let horigrid = document.createElement('input')
horigrid.style=inputstyle
horigridlabel.appendChild(document.createElement('br'))
horigridlabel.appendChild(horigrid)
horigrid.placeholder="Horizontal Gridlines"
let vertgrid = document.createElement('input')
vertgrid.style=inputstyle
vertgridlabel.appendChild(document.createElement('br'))
vertgridlabel.appendChild(vertgrid)
vertgrid.placeholder="Vertical Gridlines"
horigrid.value="0"
vertgrid.value="0"
let gridenable = document.createElement("button")
toolbar2.appendChild(gridenable)
gridenable.innerHTML="Enable Grid"
gridenable.style=buttonstyle
createtbdiv()
let altdistlabel = document.createElement("label")
toolbar2.appendChild(altdistlabel)
altdistlabel.innerHTML="Star Factor"
altdistlabel.style=labelstyle
let altdist = document.createElement('input')
altdist.style=inputstyle
altdistlabel.appendChild(document.createElement('br'))
altdistlabel.appendChild(altdist)
altdist.placeholder="Star Magnitude Factor"
altdist.value="50%"
let polysideslabel = document.createElement("label")
toolbar2.appendChild(polysideslabel)
polysideslabel.innerHTML="Star Points"
polysideslabel.style=labelstyle
let polysides = document.createElement('input')
polysides.style=inputstyle
polysideslabel.appendChild(document.createElement('br'))
polysideslabel.appendChild(polysides)
polysides.placeholder="Star Points"
polysides.value="5"
let squsecenable = document.createElement("button")
toolbar2.appendChild(squsecenable)
squsecenable.innerHTML="Enable 1:1"
squsecenable.style=buttonstyle

let origin = {
    preview: {},
    real: {}
};

const pos = {
    preview: {},
    real: {}
};

const clamp = (num, min, max) => Math.min(Math.max(num, min), max)

let canvasHidden = true;
let drawingLine = false;
let doog = "";
var bezipoints = []
var beziselec = false
var bezselec = -1
var recbezselec = -1
var gridenabled = false
var gridhori = 0
var gridvert = 0
var sidespoly = 10
var square = false
var forcesquare = false
document.addEventListener('keydown', (e) => {
    if (!isDrawing()) return;
    if (e.code === 'ShiftLeft' && canvasHidden) {
        lineCanvas.style.display = '';
        disableScroll();
        canvasHidden = false;
        lineCanvas.style.cursor="crosshair"
    } else if (!canvasHidden){
        if (doog===""){
            lineCanvas.style.cursor="crosshair"
            if (e.code==="KeyZ")doog="snap"
            if (e.code==="KeyX")doog="rect"
            if (e.code==="KeyC")doog="circ"
            if (e.code==="KeyV")doog="bezi"
            if (e.code==="KeyA")doog="rhom"
            if (e.code==="KeyS")doog="star"
        }else{
            if (e.code==="Space")square=true
        }
    }
    document.dispatchEvent(createMouseEvent('pointermove', pos.real));
});

function unfocusvert(vert,ty){
    document.activeElement.blur()
    vert.style.color="#bd2057"
    if(ty===2){
        if (vert.value.replace(/\D/g,'')===""){
            vert.value="5"
            sidespoly=Number(vert.value)*2
        }else{
            vert.value=clamp(Number(vert.value.replace(/\D/g,'')),5,18).toString()
            sidespoly=clamp(Number(vert.value.replace(/\D/g,'')),5,18)*2
        }
    }else{
        if (vert.value.replace(/\D/g,'')===""){
            vert.value="0"
            if(ty===0){gridhori=Number(vert.value)}else if(ty===1){gridvert=Number(vert.value)}
        }else{
            vert.value=clamp(Number(vert.value.replace(/\D/g,'')),0,25).toString()
            if(ty===0){gridhori=clamp(Number(vert.value.replace(/\D/g,'')),0,25)}else if(ty===1){gridvert=clamp(Number(vert.value.replace(/\D/g,'')),0,25)}
        }
    }
}
function unfocusperc(vert){
    document.activeElement.blur()
    vert.style.color="#bd2057"
    if (vert.value.replace(/\D/g,'')===""){
        vert.value="0%"
    }else{
        vert.value=clamp(Number(vert.value.replace(/\D/g,'')),0,100).toString()+'%'
    }
}

horigrid.addEventListener("keydown", ({key}) => {
    if (key === "Enter") {
        unfocusvert(horigrid,0)
    }
})
horigrid.addEventListener("focusout", () => {
    unfocusvert(horigrid,0)
})
horigrid.addEventListener("click",()=>{
    horigrid.style.color="black"
})

vertgrid.addEventListener("keydown", ({key}) => {
    if (key === "Enter") {
        unfocusvert(vertgrid,1)
    }
})
vertgrid.addEventListener("focusout", () => {
    unfocusvert(vertgrid,1)
})
vertgrid.addEventListener("click",()=>{
    vertgrid.style.color="black"
})

polysides.addEventListener("keydown", ({key}) => {
    if (key === "Enter") {
        unfocusvert(polysides,2)
    }
})
polysides.addEventListener("focusout", () => {
    unfocusvert(polysides,2)
})
polysides.addEventListener("click",()=>{
    polysides.style.color="black"
})

altdist.addEventListener("keydown", ({key}) => {
    if (key === "Enter") {
        unfocusperc(altdist)
    }
})
altdist.addEventListener("focusout", () => {
    unfocusperc(altdist)
})
altdist.addEventListener("click",()=>{
    altdist.style.color="black"
    altdist.value=altdist.value.replace('%','')
})

gridenable.addEventListener("click",()=>{
    if(gridenabled===false){
        gridenabled=true
        gridenable.innerHTML="Disable Grid"
        gridenable.style['background-image']="linear-gradient(to bottom, #f85032 0%,#f16f5c 50%,#f6290c 51%,#f02f17 71%,#e73827 100%)"
    }else{gridenabled=false;gridenable.innerHTML="Enable Grid";gridenable.style['background-image']="linear-gradient(to bottom, #bfd255 0%,#8eb92a 50%,#72aa00 51%,#9ecb2d 100%)"}
})
squsecenable.addEventListener("click",()=>{
    if(forcesquare===false){
        forcesquare=true
        squsecenable.innerHTML="Disable 1:1"
        squsecenable.style['background-image']="linear-gradient(to bottom, #f85032 0%,#f16f5c 50%,#f6290c 51%,#f02f17 71%,#e73827 100%)"
    }else{forcesquare=false;squsecenable.innerHTML="Enable 1:1";squsecenable.style['background-image']="linear-gradient(to bottom, #bfd255 0%,#8eb92a 50%,#72aa00 51%,#9ecb2d 100%)"}
})

document.addEventListener('keyup', (e) => {
    if (e.code === 'ShiftLeft' && !canvasHidden) {
        if(doog==="bezi"){
            for(let i=0;i<20;i++){
                const canvasRect = canvas.getBoundingClientRect();
                const canvasScale = canvas.width / canvasRect.width;
                let x0=bezipoints[0][0].x/canvasScale+canvasRect.left
                let x1=bezipoints[1][0].x/canvasScale+canvasRect.left
                let x2=bezipoints[2][0].x/canvasScale+canvasRect.left
                let x3=bezipoints[3][0].x/canvasScale+canvasRect.left
                let y0=bezipoints[0][0].y/canvasScale+canvasRect.top
                let y1=bezipoints[1][0].y/canvasScale+canvasRect.top
                let y2=bezipoints[2][0].y/canvasScale+canvasRect.top
                let y3=bezipoints[3][0].y/canvasScale+canvasRect.top
                let t1=i/20
                let t2=(i+1)/20
                canvas.dispatchEvent(createMouseEvent('mousedown', {x:(1-t1)*((1-t1)*((1-t1)*x0+t1*x1)+t1*((1-t1)*x1+t1*x2))+t1*((1-t1)*((1-t1)*x1+t1*x2)+t1*((1-t1)*x2+t1*x3)),y:(1-t1)*((1-t1)*((1-t1)*y0+t1*y1)+t1*((1-t1)*y1+t1*y2))+t1*((1-t1)*((1-t1)*y1+t1*y2)+t1*((1-t1)*y2+t1*y3))}, true));
                canvas.dispatchEvent(createMouseEvent('mousemove', {x:(1-t2)*((1-t2)*((1-t2)*x0+t2*x1)+t2*((1-t2)*x1+t2*x2))+t2*((1-t2)*((1-t2)*x1+t2*x2)+t2*((1-t2)*x2+t2*x3)),y:(1-t2)*((1-t2)*((1-t2)*y0+t2*y1)+t2*((1-t2)*y1+t2*y2))+t2*((1-t2)*((1-t2)*y1+t2*y2)+t2*((1-t2)*y2+t2*y3))}, true));
                canvas.dispatchEvent(createMouseEvent('mouseup', {x:(1-t2)*((1-t2)*((1-t2)*x0+t2*x1)+t2*((1-t2)*x1+t2*x2))+t2*((1-t2)*((1-t2)*x1+t2*x2)+t2*((1-t2)*x2+t2*x3)),y:(1-t2)*((1-t2)*((1-t2)*y0+t2*y1)+t2*((1-t2)*y1+t2*y2))+t2*((1-t2)*((1-t2)*y1+t2*y2)+t2*((1-t2)*y2+t2*y3))}, true));
            }
            lineCanvas.style.cursor="crosshair"
        }
        hideLineCanvas();
        document.removeEventListener('pointermove', savePos);
        document.removeEventListener('pointerup', mouseUpDraw);
    } else if (e.code === 'KeyZ' && doog === "snap" || e.code === 'KeyX' && doog === "rect" || e.code === 'KeyC' && doog === "circ" || e.code === 'KeyA' && doog === "rhom" || e.code === 'KeyS' && doog === "star") {
        doog = "";
        document.dispatchEvent(createMouseEvent('pointermove', pos.real));
    } else if (e.code==="Space"){
        square=false
    }
});

function hideLineCanvas() {
    lineCanvas.style.display = 'none';
    canvasHidden = true;
    doog=""
    bezipoints = []
    enableScroll();
    resetLineCanvas();
}

lineCanvas.addEventListener('pointerdown', (e) => {
    if (!e.shiftKey) hideLineCanvas();
    if (bezselec===-1){
        if(doog==="bezi"){
            if (bezipoints.length<4){
                bezipoints[bezipoints.length]=[getPos(e),0];
                recbezselec=bezipoints.length
            }
        }
    }else if(recbezselec!=bezselec){
        beziselec=true
        lineCanvas.style.cursor="pointer"
    }
    origin = getPos(e);
    origin.real = getRealPos(e);
    drawingLine = true;
    document.addEventListener('pointermove', savePos);
    document.addEventListener('pointerup', mouseUpDraw);
});

function savePos(e) {
    e.preventDefault();
    pos.preview = getPos(e);
    pos.real = getRealPos(e);
    if (!beziselec&&doog==="bezi"){
        let aga = [-1,9]
        for (let i=0;i<bezipoints.length;i++){
            bezipoints[i][1]=0
            if(Math.sqrt(Math.pow(pos.preview.x-bezipoints[i][0].x,2)+Math.pow(pos.preview.y-bezipoints[i][0].y,2))<=8){if(Math.sqrt(Math.pow(pos.preview.x-bezipoints[i][0].x,2)+Math.pow(pos.preview.y-bezipoints[i][0].y,2))<aga[1]){aga=[i,Math.sqrt(Math.pow(pos.preview.x-bezipoints[i][0].x,2)+Math.pow(pos.preview.y-bezipoints[i][0].y,2))]}}
        }
        bezselec=aga[0]
        if (aga[0]>-1){bezipoints[aga[0]][1]=1;lineCanvas.style.cursor="pointer"}else lineCanvas.style.cursor="crosshair"
    }else if(doog==="bezi")bezipoints[bezselec][0]=pos.preview
    if ((canvasHidden && doog!="bezi") || (!drawingLine && doog!="bezi")) return;
    if(doog!='bezi')lineCanvas.clear()
    drawPreviewLine(pos.preview);
}

function mouseUpDraw(e) {
    if (doog!="bezi"){
        document.removeEventListener('pointermove', savePos);
        document.removeEventListener('pointerup', mouseUpDraw);
        drawLine(origin.real.x, origin.real.y, pos.real.x, pos.real.y);
        pos.preview = getPos(e);
        pos.real = getRealPos(e);
        resetLineCanvas();
    }else{
        beziselec=false
        lineCanvas.style.cursor="crosshair"
        recbezselec=-1
    }
}

function resetLineCanvas() {
    drawingLine = false;
    lineCanvas.clear();
}

function getPos(event) {
    const canvasRect = canvas.getBoundingClientRect();
    const canvasScale = canvas.width / canvasRect.width;
    return {
        x: (event.clientX - canvasRect.left) * canvasScale,
        y: (event.clientY - canvasRect.top) * canvasScale
    };
}
function getRealPos(event) {
    return {
        x: event.clientX,
        y: event.clientY
    };
}

function drawPreviewLine(coords) {
    if(square||forcesquare)coords={x:origin.x+Math.min(Math.abs(coords.x-origin.x),Math.abs(coords.y-origin.y))*((coords.x-origin.x)/Math.abs(coords.x-origin.x)),y:origin.y+Math.min(Math.abs(coords.x-origin.x),Math.abs(coords.y-origin.y))*((coords.y-origin.y)/Math.abs(coords.y-origin.y))}
    linectx.beginPath();
    if (doog==="snap") {
        linectx.moveTo(origin.x, origin.y);
        let ab_x = coords.x-origin.x
        let ab_y = coords.y-origin.y
        let abc123 = Math.round((180*(Math.atan(ab_x/ab_y)+((((ab_y-Math.abs(ab_y))/ab_y)/2)*Math.PI)))/(45*Math.PI))*((Math.PI*45)/180)
        linectx.lineTo(Math.sin(abc123)*Math.sqrt(Math.pow(ab_x,2)+Math.pow(ab_y,2))+origin.x,Math.cos(abc123)*Math.sqrt(Math.pow(ab_x,2)+Math.pow(ab_y,2))+origin.y)
    } else if (doog==="rect") {
        linectx.moveTo(origin.x, origin.y);
        linectx.strokeRect(origin.x, origin.y, coords.x-origin.x, coords.y-origin.y);
    } else if (doog==="circ") {
        linectx.ellipse(origin.x+(coords.x-origin.x)/2, origin.y+(coords.y-origin.y)/2, Math.abs((coords.x-origin.x)/2), Math.abs((coords.y-origin.y)/2), 0, 0, 2*Math.PI);
    } else if (doog==="") {
        linectx.moveTo(origin.x, origin.y);
        linectx.lineTo(coords.x, coords.y);
    } else if (doog==="bezi"){
        resetLineCanvas()
        let i
        for (i=0;i<bezipoints.length;i++){
            linectx.beginPath()
            linectx.arc(bezipoints[i][0].x,bezipoints[i][0].y,8,0,2*Math.PI)
            linectx.fillStyle = 'rgba(255,'+(100*bezipoints[i][1]).toString()+','+(100*bezipoints[i][1]).toString()+',0.5)'
            linectx.fill()
            linectx.beginPath()
            linectx.arc(bezipoints[i][0].x,bezipoints[i][0].y,3,0,2*Math.PI)
            linectx.fillStyle = 'rgba(255,0,0,1)'
            linectx.fill()
            if(bezipoints.length==4){
                linectx.beginPath()
                linectx.moveTo(bezipoints[0][0].x,bezipoints[0][0].y)
                linectx.bezierCurveTo(bezipoints[1][0].x,bezipoints[1][0].y,bezipoints[2][0].x,bezipoints[2][0].y,bezipoints[3][0].x,bezipoints[3][0].y)
                linectx.stroke()
            }
        }
    } else if (doog==="rhom"){
        linectx.moveTo(origin.x,origin.y+(coords.y-origin.y)/2)
        linectx.lineTo(origin.x+(coords.x-origin.x)/2,origin.y)
        linectx.lineTo(coords.x,origin.y+(coords.y-origin.y)/2)
        linectx.lineTo(origin.x+(coords.x-origin.x)/2,coords.y)
        linectx.lineTo(origin.x,origin.y+(coords.y-origin.y)/2)
        linectx.stroke()
    } else if (doog==="star"){
        let x1=origin.x
        let x2=coords.x
        let y1=origin.y
        let y2=coords.y
        let i = 0
        linectx.moveTo((x1+(x2-x1)/2)+Math.sin(((i)*(360/sidespoly)*Math.PI)/180)*(((x2-x1)/2)-((x2-x1)/2)*(i%2)*(Number(altdist.value.replace(/\D/g,''))/100)),(y1+(y2-y1)/2)-Math.cos(((i)*(360/sidespoly)*Math.PI)/180)*(((y2-y1)/2)-((y2-y1)/2)*(i%2)*(Number(altdist.value.replace(/\D/g,''))/100)))
        for (i = 0; i<sidespoly; i++) {
            linectx.lineTo((x1+(x2-x1)/2)+Math.sin(((i)*(360/sidespoly)*Math.PI)/180)*(((x2-x1)/2)-((x2-x1)/2)*(i%2)*(Number(altdist.value.replace(/\D/g,''))/100)),(y1+(y2-y1)/2)-Math.cos(((i)*(360/sidespoly)*Math.PI)/180)*(((y2-y1)/2)-((y2-y1)/2)*(i%2)*(Number(altdist.value.replace(/\D/g,''))/100)))
            linectx.lineTo((x1+(x2-x1)/2)+Math.sin((((i+1))*(360/sidespoly)*Math.PI)/180)*(((x2-x1)/2)-((x2-x1)/2)*((i+1)%2)*(Number(altdist.value.replace(/\D/g,''))/100)),(y1+(y2-y1)/2)-Math.cos((((i+1))*(360/sidespoly)*Math.PI)/180)*(((y2-y1)/2)-((y2-y1)/2)*((i+1)%2)*(Number(altdist.value.replace(/\D/g,''))/100)))
        }
        linectx.stroke()
    }
    if (doog!="bezi"){linectx.lineWidth = 3;linectx.stroke()}
}

function drawLine(x1, y1, x2, y2) {
    if(square||forcesquare){
        x2=x1+Math.min(Math.abs(x2-x1),Math.abs(y2-y1))*((x2-x1)/Math.abs(x2-x1))
        y2=y1+Math.min(Math.abs(x2-x1),Math.abs(y2-y1))*((y2-y1)/Math.abs(y2-y1))
    }
    const coords = { x: x1, y: y1 };
    const newCoords = { x: x2, y: y2 };
    if (doog===""||doog==="snap"){
        if (doog==="snap") {
            let ab_x = x2-x1
            let ab_y = y2-y1
            let abc123 = Math.round((180*(Math.atan(ab_x/ab_y)+((((ab_y-Math.abs(ab_y))/ab_y)/2)*Math.PI)))/(45*Math.PI))*((Math.PI*45)/180)
            newCoords.x = x1+Math.sin(abc123)*Math.sqrt(Math.pow(ab_x,2)+Math.pow(ab_y,2))
            newCoords.y = y1+Math.cos(abc123)*Math.sqrt(Math.pow(ab_x,2)+Math.pow(ab_y,2))
        }
        canvas.dispatchEvent(createMouseEvent('mousedown', coords, true));
        canvas.dispatchEvent(createMouseEvent('mousemove', newCoords, true));
        canvas.dispatchEvent(createMouseEvent('mouseup', newCoords, true));
    }
    if (doog==="rect") {
        canvas.dispatchEvent(createMouseEvent('mousedown',coords,true));
        canvas.dispatchEvent(createMouseEvent('mousemove',{x:x2,y:y1},true));
        canvas.dispatchEvent(createMouseEvent('mousemove',{x:x2,y:y2},true));
        canvas.dispatchEvent(createMouseEvent('mousemove',{x:x1,y:y2},true));
        canvas.dispatchEvent(createMouseEvent('mousemove',coords,true));
        canvas.dispatchEvent(createMouseEvent('mouseup',coords,true));
        if(gridenabled===true){
            if(gridvert>0){for (let i=1;i<=gridvert;i++){
                canvas.dispatchEvent(createMouseEvent('mousedown',{x:x1,y:y1+((y2-y1)/(gridvert+1))*i},true));
                canvas.dispatchEvent(createMouseEvent('mousemove',{x:x2,y:y1+((y2-y1)/(gridvert+1))*i},true));
                canvas.dispatchEvent(createMouseEvent('mouseup',{x:x2,y:y1+((y2-y1)/(gridvert+1))*i},true));
            }}
            if(gridhori>0){for (let i=1;i<=gridhori;i++){
                canvas.dispatchEvent(createMouseEvent('mousedown',{x:x1+((x2-x1)/(gridhori+1))*i,y:y1},true));
                canvas.dispatchEvent(createMouseEvent('mousemove',{x:x1+((x2-x1)/(gridhori+1))*i,y:y2},true));
                canvas.dispatchEvent(createMouseEvent('mouseup',{x:x1+((x2-x1)/(gridhori+1))*i,y:y2},true));
            }}
        }
    }
    if (doog==="circ") {
        let i
        for (i = 0; i<36; i++) {
            canvas.dispatchEvent(createMouseEvent('mousedown', {x:(x1+(x2-x1)/2)+Math.sin(((i)*10*Math.PI)/180)*((x2-x1)/2),y:(y1+(y2-y1)/2)+Math.cos(((i)*10*Math.PI)/180)*((y2-y1)/2)}, true));
            canvas.dispatchEvent(createMouseEvent('mousemove', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*10*Math.PI)/180)*((x2-x1)/2),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*10*Math.PI)/180)*((y2-y1)/2)}, true));
            if(i===35){
                canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*10*Math.PI)/180)*((x2-x1)/2),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*10*Math.PI)/180)*((y2-y1)/2)}, true));
            }
        }
        if(gridenabled===true){
            if(gridhori>0){
                if(gridvert===0&&gridhori===1){
                    for (let ie=1;ie<=gridhori;ie++){
                        for (i = 0; i<36/(gridhori+2)*ie; i++){
                            canvas.dispatchEvent(createMouseEvent('mousedown', {x:(x1+(x2-x1)/2)+Math.sin(((i)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+2)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+2)*ie)}, true));
                            canvas.dispatchEvent(createMouseEvent('mousemove', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+2)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+2)*ie)}, true));
                            if(gridhori<=8){
                                if(i===(36/(gridhori+2)*ie)-1){
                                    canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+2)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+2)*ie)}, true));
                                }
                            }else{
                                canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+2)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*(360/(36/(gridhori+2)*ie))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+2)*ie)}, true));
                            }
                        }
                    }
                }else{
                    for (let ie=1;ie<=gridhori;ie++){
                        for (i = 0; i<clamp(36/(gridhori+1)*ie,7,36); i++){
                            canvas.dispatchEvent(createMouseEvent('mousedown', {x:(x1+(x2-x1)/2)+Math.sin(((i)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+1)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+1)*ie)}, true));
                            canvas.dispatchEvent(createMouseEvent('mousemove', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+1)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+1)*ie)}, true));
                            if(gridhori<=8){
                                if(i===(clamp(36/(gridhori+1)*ie,7,36))-1){
                                    canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+1)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+1)*ie)}, true));
                                }
                            }else{
                                canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((x2-x1)/2)/(gridhori+1)*ie),y:(y1+(y2-y1)/2)+Math.cos(((i+1)*(360/clamp(36/(gridhori+1)*ie,7,36))*Math.PI)/180)*(((y2-y1)/2)/(gridhori+1)*ie)}, true));
                            }
                        }
                    }
                }
            }
            if(gridvert>0){
                for (let i = 0; i<gridvert; i++) {
                    canvas.dispatchEvent(createMouseEvent('mousedown', {x:x1+(x2-x1)/2,y:y1+(y2-y1)/2}, true));
                    canvas.dispatchEvent(createMouseEvent('mousemove', {x:(x1+(x2-x1)/2)+Math.sin(((i)*(360/gridvert)*Math.PI)/180)*((x2-x1)/2),y:(y1+(y2-y1)/2)-Math.cos(((i)*(360/gridvert)*Math.PI)/180)*((y2-y1)/2)}, true));
                    canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i)*(360/gridvert)*Math.PI)/180)*((x2-x1)/2),y:(y1+(y2-y1)/2)-Math.cos(((i)*(360/gridvert)*Math.PI)/180)*((y2-y1)/2)}, true));
                }
            }
        }
    }
    if (doog==="rhom") {
        canvas.dispatchEvent(createMouseEvent('mousedown', {x:x1,y:y1+(y2-y1)/2}, true));
        canvas.dispatchEvent(createMouseEvent('mousemove', {x:x1+(x2-x1)/2,y:y1}, true));
        canvas.dispatchEvent(createMouseEvent('mousemove', {x:x2,y:y1+(y2-y1)/2}, true));
        canvas.dispatchEvent(createMouseEvent('mousemove', {x:x1+(x2-x1)/2,y:y2}, true));
        canvas.dispatchEvent(createMouseEvent('mousemove', {x:x1,y:y1+(y2-y1)/2}, true));
        canvas.dispatchEvent(createMouseEvent('mouseup', {x:x1,y:y1+(y2-y1)/2}, true));
        if(gridenabled===true){
            if(gridvert>0){for (let i=1;i<=gridvert;i++){
                canvas.dispatchEvent(createMouseEvent('mousedown',{x:x1+(((x2-x1)/2)/(gridvert+1))*i,y:y1+((y2-y1)/2)-(((y2-y1)/2)/(gridvert+1))*i},true));
                canvas.dispatchEvent(createMouseEvent('mousemove',{x:x1+((x2-x1)/2)+(((x2-x1)/2)/(gridvert+1))*i,y:y2-(((y2-y1)/2)/(gridvert+1))*i},true));
                canvas.dispatchEvent(createMouseEvent('mouseup',{x:x1+((x2-x1)/2)+(((x2-x1)/2)/(gridvert+1))*i,y:y2-(((y2-y1)/2)/(gridvert+1))*i},true));
            }}
            if(gridhori>0){for (let i=1;i<=gridhori;i++){
                canvas.dispatchEvent(createMouseEvent('mousedown',{x:x1+((x2-x1)/2)+(((x2-x1)/2)/(gridhori+1))*i,y:y1+(((y2-y1)/2)/(gridhori+1))*i},true));
                canvas.dispatchEvent(createMouseEvent('mousemove',{x:x1+(((x2-x1)/2)/(gridhori+1))*i,y:y1+((y2-y1)/2)+(((y2-y1)/2)/(gridhori+1))*i},true));
                canvas.dispatchEvent(createMouseEvent('mouseup',{x:x1+(((x2-x1)/2)/(gridhori+1))*i,y:y1+((y2-y1)/2)+(((y2-y1)/2)/(gridhori+1))*i},true));
            }}
        }
    }
    if (doog==="star") {
        for (let i = 0; i<sidespoly; i++) {
            canvas.dispatchEvent(createMouseEvent('mousedown', {x:(x1+(x2-x1)/2)+Math.sin(((i)*(360/sidespoly)*Math.PI)/180)*(((x2-x1)/2)-((x2-x1)/2)*(i%2)*(Number(altdist.value.replace(/\D/g,''))/100)),y:(y1+(y2-y1)/2)-Math.cos(((i)*(360/sidespoly)*Math.PI)/180)*(((y2-y1)/2)-((y2-y1)/2)*(i%2)*(Number(altdist.value.replace(/\D/g,''))/100))}, true));
            canvas.dispatchEvent(createMouseEvent('mousemove', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/sidespoly)*Math.PI)/180)*(((x2-x1)/2)-((x2-x1)/2)*((i+1)%2)*(Number(altdist.value.replace(/\D/g,''))/100)),y:(y1+(y2-y1)/2)-Math.cos(((i+1)*(360/sidespoly)*Math.PI)/180)*(((y2-y1)/2)-((y2-y1)/2)*((i+1)%2)*(Number(altdist.value.replace(/\D/g,''))/100))}, true));
            if(i===sidespoly-1){
                canvas.dispatchEvent(createMouseEvent('mouseup', {x:(x1+(x2-x1)/2)+Math.sin(((i+1)*(360/sidespoly)*Math.PI)/180)*(((x2-x1)/2)-((x2-x1)/2)*((i+1)%2)*(Number(altdist.value.replace(/\D/g,''))/100)),y:(y1+(y2-y1)/2)-Math.cos(((i+1)*(360/sidespoly)*Math.PI)/180)*(((y2-y1)/2)-((y2-y1)/2)*((i+1)%2)*(Number(altdist.value.replace(/\D/g,''))/100))}, true));
            }
        }
    }
}

function createMouseEvent(name, coords, bubbles = false) {
    return new MouseEvent(name, {
        bubbles: bubbles,
        clientX: coords.x,
        clientY: coords.y,
        button: 0
    });
}

const keys = { 32: 1, 37: 1, 38: 1, 39: 1, 40: 1 };

function preventDefault(e) {
    e.preventDefault();
}

function preventDefaultForScrollKeys(e) {
    if (keys[e.keyCode]) {
        preventDefault(e);
        return false;
    }
}

function isDrawing() {
    return document.querySelector('.containerTools').offsetParent !== null;
}

let supportsPassive = false;
try {
    window.addEventListener('test', null, Object.defineProperty({}, 'passive', {
        get: function() {
            supportsPassive = true;
            return true;
        }
    }));
}
catch(e) {
    console.log(e);
}

const wheelOpt = supportsPassive ? { passive: false } : false;
const wheelEvent = 'onwheel' in document.createElement('div') ? 'wheel' : 'mousewheel';

function disableScroll() {
    window.addEventListener('DOMMouseScroll', preventDefault, false);
    window.addEventListener(wheelEvent, preventDefault, wheelOpt);
    window.addEventListener('touchmove', preventDefault, wheelOpt);
    window.addEventListener('keydown', preventDefaultForScrollKeys, false);
}

function enableScroll() {
    window.removeEventListener('DOMMouseScroll', preventDefault, false);
    window.removeEventListener(wheelEvent, preventDefault, wheelOpt);
    window.removeEventListener('touchmove', preventDefault, wheelOpt);
    window.removeEventListener('keydown', preventDefaultForScrollKeys, false);
}

window.addEventListener('blur', hideLineCanvas);