Changed things around a bit, thinking about moving all transforms into an object..
This commit is contained in:
parent
9b5e9e9500
commit
c21f39edbe
26
README.md
26
README.md
@ -41,9 +41,18 @@ Ronin helpers are keywords that facilitates adding coordinates from the canvas i
|
||||
- `(import path shape ~alpha)` Imports a graphic file with format.
|
||||
- `(export path ~format ~quality)` Exports a graphic file with format.
|
||||
- `(open path ~ratio)` Imports a graphic file and resizes the frame.
|
||||
- `(frame)` Returns a rect of the frame.
|
||||
- `(resize ~w)` Resizes the canvas to target w and h, returns the rect.
|
||||
- `(rescale ~w ~h)` Rescales the canvas to target ratio of w and h, returns the rect.
|
||||
- `(crop ~rect)` Crop canvas to rect.
|
||||
- `(copy ~rect)` Copy a section of the canvas.
|
||||
- `(paste copy ~rect)` Paste a section of the canvas.
|
||||
- `(drag ~rect)` Drag a part of the canvas.
|
||||
- `(view a b)` View a part of the canvas.
|
||||
- `(pick ~shape)` Returns the color of a pixel at pos, or of the average of the pixels in rect.
|
||||
- `(move x y)`
|
||||
- `(rotate angle)`
|
||||
- `(scale x y)`
|
||||
- `(scale w h)`
|
||||
- `(transform a b c d e f)`
|
||||
- `(setTransform a b c d e f)`
|
||||
- `(resetTransform)`
|
||||
@ -59,24 +68,11 @@ Ronin helpers are keywords that facilitates adding coordinates from the canvas i
|
||||
- `(text x y p t ~a ~f)` Returns a text shape.
|
||||
- `(svg x y d)` Returns a svg shape.
|
||||
- `(color r g b ~a)` Returns a color object.
|
||||
- `(offset a b)` Offsets pos a with pos b, returns a.
|
||||
- `(distance a b)` Get distance between positions.
|
||||
- `(stroke shape color ~thickness)` Strokes a shape.
|
||||
- `(fill ~rect)` Fills a shape.
|
||||
- `(gradient line ~colors 'black'])` Defines a gradient color.
|
||||
- `(guide shape color)` Draws a shape on the guide layer.
|
||||
- `(clear ~rect)` Clears a rect.
|
||||
- `(frame)` Returns a rect of the frame.
|
||||
- `(center)` Returns a position of the center of the frame.
|
||||
- `(resize ~w)` Resizes the canvas to target w and h, returns the rect.
|
||||
- `(rescale w h)` Rescales the canvas to target ratio of w and h, returns the rect.
|
||||
- `(crop ~rect)` Crop canvas to rect.
|
||||
- `(copy ~rect)` Copy a section of the canvas.
|
||||
- `(paste copy ~rect)` Paste a section of the canvas.
|
||||
- `(clone a b)`
|
||||
- `(drag ~rect)` Drag a part of the canvas.
|
||||
- `(view a b)` View a part of the canvas.
|
||||
- `(pick ~shape)` Returns the color of a pixel at pos, or of the average of the pixels in rect.
|
||||
- `(theme variable ~el)`
|
||||
- `(pixels fn ~q ~rect)`
|
||||
- `(saturation pixel q)` Change the saturation of pixels.
|
||||
@ -139,6 +135,8 @@ Ronin helpers are keywords that facilitates adding coordinates from the canvas i
|
||||
- `(dirname ~path)` Returns the name of a folder.
|
||||
- `(filename ~path)` Returns the name of a file.
|
||||
- `(exit ~force)` Exits Ronin.
|
||||
- `(offset a b)` Offsets pos a with pos b, returns a.
|
||||
- `(distance a b)` Get distance between positions.
|
||||
- `(echo ...args)` Print arguments to interface.
|
||||
- `(debug arg)` Print arguments to console.
|
||||
- `(time ~rate)` Returns timestamp in milliseconds.
|
||||
|
@ -182,7 +182,7 @@ function Commander (ronin) {
|
||||
if (word === 'pos') { return `(pos ${shape.x} ${shape.y})` }
|
||||
if (word === 'line') { return `(line ${shape.a.x} ${shape.a.y} ${shape.b.x} ${shape.b.y})` }
|
||||
if (word === 'circle') { return `(circle ${shape.cx} ${shape.cy} ${shape.r})` }
|
||||
if (word === 'x' || word === 'y' || word === 'xy') { return `${shape}` }
|
||||
if (word === 'x' || word === 'y' || word === 'xy' || word === 'wh') { return `${shape}` }
|
||||
return ''
|
||||
}
|
||||
|
||||
|
@ -21,6 +21,75 @@ function Library (ronin) {
|
||||
return ronin.surface.open(path, ratio)
|
||||
}
|
||||
|
||||
// Frame
|
||||
|
||||
this.frame = () => { // Returns a rect of the frame.
|
||||
return ronin.surface.getFrame()
|
||||
}
|
||||
|
||||
this.resize = async (w = ronin.surface.bounds().w, h = ronin.surface.bounds().h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
|
||||
if (w === this.frame().w && h === this.frame().h) { return }
|
||||
const rect = { x: 0, y: 0, w, h }
|
||||
const a = document.createElement('img')
|
||||
const b = document.createElement('img')
|
||||
a.src = ronin.surface.el.toDataURL()
|
||||
await ronin.surface.resizeImage(a, b)
|
||||
ronin.surface.resize(rect, fit)
|
||||
return ronin.surface.draw(b, rect)
|
||||
}
|
||||
|
||||
this.rescale = async (w = 1, h = 1) => { // Rescales the canvas to target ratio of w and h, returns the rect.
|
||||
const rect = { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h }
|
||||
const a = document.createElement('img')
|
||||
const b = document.createElement('img')
|
||||
a.src = ronin.surface.el.toDataURL()
|
||||
await ronin.surface.resizeImage(a, b)
|
||||
ronin.surface.resize(rect, true)
|
||||
return ronin.surface.draw(b, rect)
|
||||
}
|
||||
|
||||
this.crop = async (rect = this.frame()) => { // Crop canvas to rect.
|
||||
return ronin.surface.crop(rect)
|
||||
}
|
||||
|
||||
this.copy = async (rect = this.frame()) => { // Copy a section of the canvas.
|
||||
return ronin.surface.copy(rect)
|
||||
}
|
||||
|
||||
this.paste = async (copy, rect = this.frame()) => { // Paste a section of the canvas.
|
||||
return ronin.surface.paste(copy, rect)
|
||||
}
|
||||
|
||||
this.drag = (rect = this.frame(), line = this.line()) => { // Drag a part of the canvas.
|
||||
const pos = { x: line.b.x - line.a.x, y: line.b.y - line.a.y }
|
||||
const crop = ronin.surface.copy(rect)
|
||||
ronin.surface.clear(rect)
|
||||
this.guide({ a: { x: rect.x, y: rect.y }, b: { x: pos.x + rect.x, y: pos.y + rect.y } })
|
||||
this.guide(rect)
|
||||
this.guide(this.offset(rect, { x: pos.x, y: pos.y }))
|
||||
ronin.surface.context.drawImage(crop, rect.x, rect.y)
|
||||
}
|
||||
|
||||
this.view = (a, b) => { // View a part of the canvas.
|
||||
this.guide({ a: { x: a.x, y: a.y }, b: { x: b.x, y: b.y } })
|
||||
this.guide(a)
|
||||
this.guide(b)
|
||||
ronin.surface.context.drawImage(this.copy(a), b.x, b.y, b.w, b.h)
|
||||
}
|
||||
|
||||
this.pick = (shape = this.frame()) => { // Returns the color of a pixel at pos, or of the average of the pixels in rect.
|
||||
const rect = shape.w && shape.h ? shape : this.rect(shape.x, shape.y, 1, 1)
|
||||
const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
|
||||
const sum = [0, 0, 0]
|
||||
const count = img.data.length / 4
|
||||
for (let i = 0, loop = img.data.length; i < loop; i += 4) {
|
||||
sum[0] += img.data[i]
|
||||
sum[1] += img.data[i + 1]
|
||||
sum[2] += img.data[i + 2]
|
||||
}
|
||||
return this.color(this.floor(sum[0] / count), this.floor(sum[1] / count), this.floor(sum[2] / count))
|
||||
}
|
||||
|
||||
// Transforms
|
||||
|
||||
this.move = (x, y) => {
|
||||
@ -31,8 +100,8 @@ function Library (ronin) {
|
||||
ronin.surface.context.rotate(angle)
|
||||
}
|
||||
|
||||
this.scale = (x, y) => {
|
||||
ronin.surface.context.scale(x, y === undefined ? x : y)
|
||||
this.scale = (w, h) => {
|
||||
ronin.surface.context.scale(w, h === undefined ? w : h)
|
||||
}
|
||||
|
||||
this.transform = (a, b, c, d, e, f) => {
|
||||
@ -96,17 +165,7 @@ function Library (ronin) {
|
||||
|
||||
this.color = (r, g, b, a = 1) => { // Returns a color object.
|
||||
const hex = '#' + ('0' + parseInt(r, 10).toString(16)).slice(-2) + ('0' + parseInt(g, 10).toString(16)).slice(-2) + ('0' + parseInt(b, 10).toString(16)).slice(-2)
|
||||
return { r, g, b, a, hex, toString: () => { return `rgba(${r},${g},${b},${a})` }, 0: r, 1: g, 2: b, 3: a, f: [r / 255, g / 255, b / 255] }
|
||||
}
|
||||
|
||||
this.offset = (a, b) => { // Offsets pos a with pos b, returns a.
|
||||
a.x += b.x
|
||||
a.y += b.y
|
||||
return a
|
||||
}
|
||||
|
||||
this.distance = (a, b) => { // Get distance between positions.
|
||||
return Math.sqrt(((ax - bx) * (ax - bx)) + ((ay - by) * (ay - by)))
|
||||
return { r, g, b, a, hex, toString: () => { return `rgba(${r},${g},${b},${a})` }, 0: r, 1: g, 2: b, 3: a, f: [r / 255, g / 255, b / 255, a] }
|
||||
}
|
||||
|
||||
// Actions
|
||||
@ -122,7 +181,11 @@ function Library (ronin) {
|
||||
}
|
||||
|
||||
this.gradient = (line, colors = ['white', 'black']) => { // Defines a gradient color.
|
||||
return ronin.surface.linearGradient(line.a.x, line.a.y, line.b.x, line.b.y, colors)
|
||||
const gradient = ronin.surface.context.createLinearGradient(line.a.x, line.a.y, line.b.x, line.b.y)
|
||||
colors.forEach((color, i) => {
|
||||
gradient.addColorStop(i * (1 / (colors.length - 1)), color)
|
||||
})
|
||||
return gradient
|
||||
}
|
||||
|
||||
this.guide = (shape, color) => { // Draws a shape on the guide layer.
|
||||
@ -136,85 +199,6 @@ function Library (ronin) {
|
||||
return rect
|
||||
}
|
||||
|
||||
// Frame
|
||||
|
||||
this.frame = () => { // Returns a rect of the frame.
|
||||
return ronin.surface.getFrame()
|
||||
}
|
||||
|
||||
this.center = () => { // Returns a position of the center of the frame.
|
||||
const rect = this.frame()
|
||||
return this.pos(rect.w / 2, rect.h / 2)
|
||||
}
|
||||
|
||||
this.resize = async (w = ronin.surface.bounds().w, h = ronin.surface.bounds().h, fit = true) => { // Resizes the canvas to target w and h, returns the rect.
|
||||
if (w === this.frame().w && h === this.frame().h) { return }
|
||||
const rect = { x: 0, y: 0, w, h }
|
||||
const a = document.createElement('img')
|
||||
const b = document.createElement('img')
|
||||
a.src = ronin.surface.el.toDataURL()
|
||||
await ronin.surface.resizeImage(a, b)
|
||||
ronin.surface.resize(rect, fit)
|
||||
return ronin.surface.draw(b, rect)
|
||||
}
|
||||
|
||||
this.rescale = async (w, h) => { // Rescales the canvas to target ratio of w and h, returns the rect.
|
||||
const rect = { x: 0, y: 0, w: this.frame().w * w, h: this.frame().h * h }
|
||||
const a = document.createElement('img')
|
||||
const b = document.createElement('img')
|
||||
a.src = ronin.surface.el.toDataURL()
|
||||
await ronin.surface.resizeImage(a, b)
|
||||
ronin.surface.resize(rect, true)
|
||||
return ronin.surface.draw(b, rect)
|
||||
}
|
||||
|
||||
this.crop = async (rect = this.frame()) => { // Crop canvas to rect.
|
||||
return ronin.surface.crop(rect)
|
||||
}
|
||||
|
||||
this.copy = async (rect = this.frame()) => { // Copy a section of the canvas.
|
||||
return ronin.surface.copy(rect)
|
||||
}
|
||||
|
||||
this.paste = async (copy, rect = this.frame()) => { // Paste a section of the canvas.
|
||||
return ronin.surface.paste(copy, rect)
|
||||
}
|
||||
|
||||
this.clone = (a, b) => {
|
||||
ronin.surface.clone(a, b)
|
||||
return [a, b]
|
||||
}
|
||||
|
||||
this.drag = (rect = this.frame(), line = this.line()) => { // Drag a part of the canvas.
|
||||
const pos = { x: line.b.x - line.a.x, y: line.b.y - line.a.y }
|
||||
const crop = ronin.surface.copy(rect)
|
||||
ronin.surface.clear(rect)
|
||||
this.guide({ a: { x: rect.x, y: rect.y }, b: { x: pos.x + rect.x, y: pos.y + rect.y } })
|
||||
this.guide(rect)
|
||||
this.guide(this.offset(rect, { x: pos.x, y: pos.y }))
|
||||
ronin.surface.context.drawImage(crop, rect.x, rect.y)
|
||||
}
|
||||
|
||||
this.view = (a, b) => { // View a part of the canvas.
|
||||
this.guide({ a: { x: a.x, y: a.y }, b: { x: b.x, y: b.y } })
|
||||
this.guide(a)
|
||||
this.guide(b)
|
||||
ronin.surface.context.drawImage(ronin.surface.copy(a), b.x, b.y, b.w, b.h)
|
||||
}
|
||||
|
||||
this.pick = (shape = this.frame()) => { // Returns the color of a pixel at pos, or of the average of the pixels in rect.
|
||||
const rect = shape.w && shape.h ? shape : this.rect(shape.x, shape.y, 1, 1)
|
||||
const img = ronin.surface.context.getImageData(rect.x, rect.y, rect.w, rect.h)
|
||||
const sum = [0, 0, 0]
|
||||
const count = img.data.length / 4
|
||||
for (let i = 0, loop = img.data.length; i < loop; i += 4) {
|
||||
sum[0] += img.data[i]
|
||||
sum[1] += img.data[i + 1]
|
||||
sum[2] += img.data[i + 2]
|
||||
}
|
||||
return this.color(this.floor(sum[0] / count), this.floor(sum[1] / count), this.floor(sum[2] / count))
|
||||
}
|
||||
|
||||
this.theme = (variable, el = document.documentElement) => {
|
||||
// ex. (theme "f_main") -> :root { --f_main: "#fff" }
|
||||
return getComputedStyle(el).getPropertyValue(`--${variable}`)
|
||||
@ -547,6 +531,16 @@ function Library (ronin) {
|
||||
ronin.source.quit(force)
|
||||
}
|
||||
|
||||
this.offset = (a, b) => { // Offsets pos a with pos b, returns a.
|
||||
a.x += b.x
|
||||
a.y += b.y
|
||||
return a
|
||||
}
|
||||
|
||||
this.distance = (a, b) => { // Get distance between positions.
|
||||
return Math.sqrt(((ax - bx) * (ax - bx)) + ((ay - by) * (ay - by)))
|
||||
}
|
||||
|
||||
this.echo = (...args) => { // Print arguments to interface.
|
||||
ronin.log(args)
|
||||
return args
|
||||
|
@ -152,6 +152,7 @@ function Ronin () {
|
||||
w: this.mouseOrigin.x ? pos.x - this.mouseOrigin.x : 0,
|
||||
h: this.mouseOrigin.y ? pos.y - this.mouseOrigin.y : 0
|
||||
}
|
||||
const wh = rect.w + ' ' + rect.h
|
||||
const line = {
|
||||
a: { x: this.mouseOrigin.x, y: this.mouseOrigin.y },
|
||||
b: { x: pos.x, y: pos.y }
|
||||
@ -163,7 +164,7 @@ function Ronin () {
|
||||
r: d.toFixed(2),
|
||||
edge: { x: rect.x - rect.w, y: rect.y - rect.h, w: rect.w * 2, h: rect.h * 2 }
|
||||
}
|
||||
return { x, y, xy, d, line, rect, pos, circle, type, 'is-down': type !== 'mouse-up' ? true : null }
|
||||
return { x, y, xy, wh, d, line, rect, pos, circle, type, 'is-down': type !== 'mouse-up' ? true : null }
|
||||
}
|
||||
|
||||
// Zoom
|
||||
|
@ -71,15 +71,6 @@ function Surface (ronin) {
|
||||
context.closePath()
|
||||
}
|
||||
|
||||
this.linearGradient = function (x1, y1, x2, y2, colors, context = this.context) {
|
||||
const gradient = context.createLinearGradient(x1, y1, x2, y2)
|
||||
const step = 1 / (colors.length - 1)
|
||||
colors.forEach((color, i) => {
|
||||
gradient.addColorStop(i * step, color)
|
||||
})
|
||||
return gradient
|
||||
}
|
||||
|
||||
// Tracers
|
||||
|
||||
this.trace = function (shape, context) {
|
||||
@ -113,13 +104,11 @@ function Surface (ronin) {
|
||||
}
|
||||
|
||||
this.traceLine = function (line, context) {
|
||||
console.log(line)
|
||||
context.moveTo(line.a.x, line.a.y)
|
||||
context.lineTo(line.b.x, line.b.y)
|
||||
}
|
||||
|
||||
this.tracePoly = function (poly, context) {
|
||||
console.log('poly?')
|
||||
const positions = Object.values(poly)
|
||||
const origin = positions.shift()
|
||||
context.moveTo(origin.x, origin.y)
|
||||
@ -206,7 +195,6 @@ function Surface (ronin) {
|
||||
}
|
||||
|
||||
this.drawGuide = function (shape, color = 'white', context = this.guide) {
|
||||
console.log(shape)
|
||||
if (!shape) { return }
|
||||
this.stroke(shape.rect || shape, 'black', 4, context)
|
||||
if (shape.pos) { this.stroke(shape.pos, 'black', 4, context) }
|
||||
@ -223,10 +211,6 @@ function Surface (ronin) {
|
||||
}
|
||||
}
|
||||
|
||||
this.clone = function (a, b) {
|
||||
this.context.drawImage(this.el, a.x, a.y, a.w, a.h, b.x, b.y, b.w, b.h)
|
||||
}
|
||||
|
||||
this.resize = function (size, fit = false) {
|
||||
const frame = this.getFrame()
|
||||
if (frame.w === size.w && frame.h === size.h) { return }
|
||||
@ -280,7 +264,7 @@ function Surface (ronin) {
|
||||
}
|
||||
|
||||
this.paste = function (copy, rect) {
|
||||
return this.context.drawImage(copy, 0, 0, rect.w, rect.h, rect.x, rect.y, rect.w, rect.h)
|
||||
return this.context.drawImage(copy, rect.x, rect.y, rect.w, rect.h)
|
||||
}
|
||||
|
||||
this.resizeImage = function (src, dst, type = 'image/png', quality = 1.0) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user