import images via drag&drop

This commit is contained in:
Skyler Lehmkuhl 2024-11-18 02:07:17 -05:00
parent 02de0b0afa
commit d37b0b0450
1 changed files with 111 additions and 13 deletions

View File

@ -30,13 +30,16 @@ let tools = {
properties: { properties: {
"lineWidth": { "lineWidth": {
type: "number", type: "number",
// default: 5,
label: "Line Width" label: "Line Width"
}, },
"simplifyMode": { "simplifyMode": {
type: "enum", type: "enum",
options: ["corners", "smooth"], // "auto"], options: ["corners", "smooth"], // "auto"],
label: "Line Mode" label: "Line Mode"
},
"fillShape": {
type: "boolean",
label: "Fill Shape"
} }
} }
}, },
@ -44,8 +47,12 @@ let tools = {
icon: "/assets/rectangle.svg", icon: "/assets/rectangle.svg",
properties: {} properties: {}
}, },
polygon: { ellipse: {
icon: "assets/polygon.svg", icon: "assets/ellipse.svg",
properties: {}
},
paint_bucket: {
icon: "/assets/paint_bucket.svg",
properties: {} properties: {}
} }
} }
@ -66,6 +73,7 @@ let context = {
], ],
lineWidth: 5, lineWidth: 5,
simplifyMode: "smooth", simplifyMode: "smooth",
fillShape: true,
} }
let config = { let config = {
@ -130,19 +138,31 @@ class Frame {
} }
class Shape { class Shape {
constructor(startx, starty, context, filled=true, stroked=true) { constructor(startx, starty, context, stroked=true) {
this.startx = startx; this.startx = startx;
this.starty = starty; this.starty = starty;
this.curves = []; this.curves = [];
this.fillStyle = context.fillStyle; this.fillStyle = context.fillStyle;
this.fillImage = context.fillImage;
this.strokeStyle = context.strokeStyle; this.strokeStyle = context.strokeStyle;
this.lineWidth = context.lineWidth this.lineWidth = context.lineWidth
this.filled = filled; this.filled = context.fillShape;
this.stroked = stroked; this.stroked = stroked;
} }
addCurve(curve) { addCurve(curve) {
this.curves.push(curve) this.curves.push(curve)
} }
addLine(x, y) {
let lastpoint;
if (this.curves.length) {
lastpoint = this.curves[this.curves.length - 1]
} else {
lastpoint = {x: this.startx, y: this.starty}
}
let midpoint = {x: (x + lastpoint.x) / 2, y: (y + lastpoint.y) / 2}
let curve = new Curve(midpoint.x, midpoint.y, midpoint.x, midpoint.y, x, y)
this.curves.push(curve)
}
simplify(mode="corners") { simplify(mode="corners") {
// Mode can be corners, smooth or auto // Mode can be corners, smooth or auto
if (mode=="corners") { if (mode=="corners") {
@ -176,7 +196,7 @@ class GraphicsObject {
constructor() { constructor() {
this.x = 0; this.x = 0;
this.y = 0; this.y = 0;
this.rotation = 0; this.rotation = 0; // in radians
this.scale = 1; this.scale = 1;
this.idx = uuidv4() this.idx = uuidv4()
@ -188,16 +208,22 @@ class GraphicsObject {
} }
draw(context) { draw(context) {
let ctx = context.ctx; let ctx = context.ctx;
ctx.translate(this.x, this.y)
ctx.rotate(this.rotation)
if (this.currentFrame>=this.frames.length) { if (this.currentFrame>=this.frames.length) {
this.currentFrame = 0; this.currentFrame = 0;
} }
for (let child of this.children) { for (let child of this.children) {
let idx = child.idx let idx = child.idx
child.x = this.frames[this.currentFrame][idx].x; if (idx in this.frames[this.currentFrame].keys) {
child.y = this.frames[this.currentFrame][idx].y; child.x = this.frames[this.currentFrame].keys[idx].x;
child.rotation = this.frames[this.currentFrame][idx].rotation; child.y = this.frames[this.currentFrame].keys[idx].y;
child.scale = this.frames[this.currentFrame][idx].scale; child.rotation = this.frames[this.currentFrame].keys[idx].rotation;
child.scale = this.frames[this.currentFrame].keys[idx].scale;
ctx.save()
child.draw(context) child.draw(context)
ctx.restore()
}
} }
for (let shape of this.frames[this.currentFrame].shapes) { for (let shape of this.frames[this.currentFrame].shapes) {
ctx.beginPath() ctx.beginPath()
@ -212,7 +238,12 @@ class GraphicsObject {
// ctx.fill() // ctx.fill()
} }
if (shape.filled) { if (shape.filled) {
if (shape.fillImage) {
let pat = ctx.createPattern(shape.fillImage, "no-repeat")
ctx.fillStyle = pat
} else {
ctx.fillStyle = shape.fillStyle ctx.fillStyle = shape.fillStyle
}
ctx.fill() ctx.fill()
} }
if (shape.stroked) { if (shape.stroked) {
@ -224,6 +255,16 @@ class GraphicsObject {
addShape(shape) { addShape(shape) {
this.frames[this.currentFrame].shapes.push(shape) this.frames[this.currentFrame].shapes.push(shape)
} }
addObject(object, x=0, y=0) {
this.children.push(object)
let idx = object.idx
this.frames[this.currentFrame].keys[idx] = {
x: x,
y: y,
rotation: 0,
scale: 1,
}
}
} }
let root = new GraphicsObject(); let root = new GraphicsObject();
@ -262,6 +303,51 @@ function stage() {
stage.width = 1500 stage.width = 1500
stage.height = 1000 stage.height = 1000
scroller.className = "scroll" scroller.className = "scroll"
stage.addEventListener("drop", (e) => {
e.preventDefault()
let mouse = getMousePos(stage, e)
const imageTypes = ['image/png', 'image/gif', 'image/avif', 'image/jpeg',
'image/svg+xml', 'image/webp'
];
if (e.dataTransfer.items) {
let i = 0
for (let item of e.dataTransfer.items) {
if (item.kind == "file") {
let file = item.getAsFile()
if (imageTypes.includes(file.type)) {
let img = new Image()
img.src = window.URL.createObjectURL(file)
img.ix = i
img.onload = function() {
let width = img.width
let height = img.height
let imageObject = new GraphicsObject()
let ct = {
...context,
fillImage: img,
}
let imageShape = new Shape(0, 0, ct, false)
imageShape.addLine(width, 0)
imageShape.addLine(width, height)
imageShape.addLine(0, height)
imageShape.addLine(0, 0)
imageObject.addShape(imageShape)
context.activeObject.addObject(
imageObject,
mouse.x-width/2 + (20*img.ix),
mouse.y-height/2 + (20*img.ix))
updateUI()
}
}
i++;
}
}
} else {
}
})
stage.addEventListener("dragover", (e) => {
e.preventDefault()
})
canvases.push(stage) canvases.push(stage)
scroller.appendChild(stage) scroller.appendChild(stage)
stage.addEventListener("mousedown", (e) => { stage.addEventListener("mousedown", (e) => {
@ -330,6 +416,9 @@ function toolbar() {
icon.src = tools[tool].icon icon.src = tools[tool].icon
toolbtn.appendChild(icon) toolbtn.appendChild(icon)
tools_scroller.appendChild(toolbtn) tools_scroller.appendChild(toolbtn)
toolbtn.addEventListener("click", () => {
console.log(tool)
})
} }
let tools_break = document.createElement("div") let tools_break = document.createElement("div")
tools_break.className = "horiz_break" tools_break.className = "horiz_break"
@ -415,6 +504,12 @@ function infopanel() {
} }
input.value = getProperty(context, property) input.value = getProperty(context, property)
break; break;
case "boolean":
input = document.createElement("input")
input.className = "infopanel-input"
input.type = "checkbox"
input.checked = getProperty(context, property)
break;
} }
input.addEventListener("input", () => { input.addEventListener("input", () => {
console.log(input.value) console.log(input.value)
@ -426,9 +521,11 @@ function infopanel() {
break; break;
case "enum": case "enum":
if (prop.options.indexOf(input.value) >= 0) { if (prop.options.indexOf(input.value) >= 0) {
// console.log(input.value)
setProperty(context, property, input.value) setProperty(context, property, input.value)
} }
break;
case "boolean":
setProperty(context, property, input.checked)
} }
}) })
@ -540,6 +637,7 @@ function updateLayout(element) {
function updateUI() { function updateUI() {
for (let canvas of canvases) { for (let canvas of canvases) {
let ctx = canvas.getContext("2d") let ctx = canvas.getContext("2d")
ctx.reset();
ctx.fillStyle = "white" ctx.fillStyle = "white"
ctx.fillRect(0,0,canvas.width,canvas.height) ctx.fillRect(0,0,canvas.width,canvas.height)
ctx.fillStyle = "green" ctx.fillStyle = "green"