russian-book-story/app/javascript/controllers/canvas_preview_controller.js
viktorvsk f3d33199f0
Some checks failed
CI / Lint & Test (push) Has been cancelled
Deploy Status Page / Build & Deploy (push) Has been cancelled
Волшебная Книга: Russian book storytelling app
- Book-styled UI with parchment aesthetic and Russian navigation
- Characters model with Konva.js 2D canvas drawing (draggable shapes)
- StoryPages model with character association and page navigation
- Stimulus controllers: canvas (editor) + canvas-preview (read-only)
- Full Russian interface: all labels, buttons, flash messages in Russian
2026-04-25 15:29:15 +00:00

51 lines
1.7 KiB
JavaScript

import { Controller } from "@hotwired/stimulus"
import Konva from "konva"
// Read-only Konva canvas for character previews
export default class extends Controller {
static values = { data: String }
connect() {
if (!this.dataValue) return
const w = this.element.offsetWidth || 300
const h = this.element.offsetHeight || 400
// Replace canvas element with a div for Konva to own
const div = document.createElement("div")
div.style.width = w + "px"
div.style.height = h + "px"
this.element.replaceWith(div)
const stage = new Konva.Stage({ container: div, width: w, height: h })
const layer = new Konva.Layer()
stage.add(layer)
// Scale to fit if saved canvas was larger
const saved = JSON.parse(this.dataValue)
const scaleX = w / (saved.attrs?.width || 380)
const scaleY = h / (saved.attrs?.height || 480)
const scale = Math.min(scaleX, scaleY)
layer.scale({ x: scale, y: scale })
layer.add(new Konva.Rect({ x: 0, y: 0, width: w / scale, height: h / scale, fill: "#f0e4c8", listening: false }))
if (saved.children) {
saved.children.forEach(child => {
let shape
switch (child.className) {
case "Circle": shape = new Konva.Circle(child.attrs); break
case "Rect": shape = new Konva.Rect(child.attrs); break
case "Ellipse": shape = new Konva.Ellipse(child.attrs); break
case "Arc": shape = new Konva.Arc(child.attrs); break
case "Star": shape = new Konva.Star(child.attrs); break
default: return
}
if (shape) { shape.listening(false); layer.add(shape) }
})
}
layer.draw()
}
}