Changed things around a bit, thinking about moving all transforms into an object..

This commit is contained in:
Devine Lu Linvega 2019-08-02 13:09:06 +09:00
parent 9b5e9e9500
commit c21f39edbe
5 changed files with 103 additions and 126 deletions

View File

@ -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.

View File

@ -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 ''
}

View File

@ -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

View File

@ -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

View File

@ -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) {