Skip to content

Instantly share code, notes, and snippets.

@megganeturner
Last active August 15, 2018 06:02
Show Gist options
  • Save megganeturner/a616f650f9f0d94fb0b85d8b82a4ce75 to your computer and use it in GitHub Desktop.
Save megganeturner/a616f650f9f0d94fb0b85d8b82a4ce75 to your computer and use it in GitHub Desktop.
Image Crop 2
import Ember from 'ember';
import { computed, observer } from '@ember/object';
import { on } from '@ember/object/evented';
export default Ember.Component.extend({
scale: 0.4,
click: false,
baseX: 0,
baseY: 0,
lastPointX: 0,
lastPointY: 0,
windowHeight: 300,
imageEl: null,
isClicking: false,
checkScale: observer('scale', function o () {
const x = this.get('baseX');
const y = this.get('baseY');
this._drawImage(this.get('canvasElement'), this.lastPointX, this.lastPointY);
}),
canvasElement: computed(function p () {
const component = this.get('element');
return component.getElementsByTagName('canvas')[0];
}),
_drawImage (el, x, y) {
const image = this.get('imageEl');
const canvasCtx = el.getContext('2d');
const scale = this.get('scale');
const windowHeight = this.get('windowHeight');
const windowWidth = this.get('windowHeight');
const canvasHeight = canvasCtx.canvas.height;
const canvasWidth = canvasCtx.canvas.width;
const newBaseX = this.get('baseX') + (x - this.get('lastPointX'));
const newBaseY = this.get('baseY') + (y - this.get('lastPointY'));
this.set('baseX', newBaseX);
this.set('baseY', newBaseY);
this.set('lastPointX', x);
this.set('lastPointY', y);
// set bounds so that the image can never leave the canvas (based on width/height & baseX/baseY)
const imageWidth = Math.floor(image.width * scale);
const imageHeight = Math.floor(image.height * scale);
canvasCtx.imageSmoothingEnabled = false;
canvasCtx.clearRect(0, 0, el.width, el.height);
let xLimit = newBaseX;
let yLimit = newBaseY;
const outerWindowWidth = (canvasWidth - windowWidth) / 2;
const outerWindowHeight = (canvasHeight - windowHeight) / 2;
const rightWindowEdgeDist = windowWidth + outerWindowWidth;
const bottomWindowEdgeDist = windowHeight + outerWindowHeight;
if (newBaseX > outerWindowWidth) {
// right bound hit
xLimit = outerWindowWidth;
}
if (Math.sign(newBaseX) === -1 && Math.abs(newBaseX) > imageWidth - rightWindowEdgeDist) {
// left bound hit
xLimit = -(imageWidth - rightWindowEdgeDist);
}
if (Math.sign(newBaseY) === -1 && Math.abs(newBaseY) > imageHeight - bottomWindowEdgeDist) {
// top bound hit
yLimit = -(imageHeight - bottomWindowEdgeDist);
}
if (newBaseY > outerWindowHeight) {
// bottom bound hit
yLimit = outerWindowHeight;
}
canvasCtx.drawImage(image, xLimit, yLimit, imageWidth, imageHeight);
this._drawWindow();
},
didInsertElement () {
this._super(...arguments);
const canvasElement = this.get('canvasElement');
const canvasCtx = canvasElement.getContext('2d');
const scale = this.get('scale');
const image = new Image();
image.src = 'https://peopledotcom.files.wordpress.com/2018/08/beyonce-4.jpg';
this.set('imageEl', image);
const drawWindow = this._drawWindow.bind(this);
image.onload = function x () {
canvasCtx.drawImage(image, 0, 0, Math.floor(image.width * scale), Math.floor(image.height * scale));
drawWindow();
}
canvasCtx.canvas.onmousedown = this._onMouseDown.bind(this);
canvasCtx.canvas.onmousemove = this._onMouseMove.bind(this);
canvasCtx.canvas.onmouseup = this._onMouseUp.bind(this);
},
_drawWindow () {
const canvasElement = this.get('canvasElement');
const canvasCtx = canvasElement.getContext('2d');
const wh = this.get('windowHeight');
const cw = canvasCtx.canvas.width;
const ch = canvasCtx.canvas.height;
const topLeftWindowX = (cw - wh) / 2;
const topLeftWindowY = (ch - wh) / 2;
const bottomRightWindowX = topLeftWindowX + wh;
const bottomRightWindowY = topLeftWindowY + wh;
const midpointX = cw / 2;
const midpointY = ch / 2;
const radius = wh / 2;
canvasCtx.fillStyle = 'rgba(255, 255, 255, 0.3)';
canvasCtx.beginPath();
canvasCtx.rect(0, 0, cw, ch);
canvasCtx.closePath();
canvasCtx.fill();
canvasCtx.fillStyle = 'rgba(255, 255, 255, 0.3)';
canvasCtx.beginPath();
canvasCtx.moveTo(midpointX, topLeftWindowY);
canvasCtx.arcTo(bottomRightWindowX, topLeftWindowY, bottomRightWindowX, midpointY, radius);
canvasCtx.arcTo(bottomRightWindowX, bottomRightWindowY, midpointX, bottomRightWindowY, radius);
canvasCtx.arcTo(topLeftWindowX, bottomRightWindowY, topLeftWindowX, midpointY, radius);
canvasCtx.arcTo(topLeftWindowX, topLeftWindowY, midpointX, topLeftWindowY, radius);
canvasCtx.closePath();
canvasCtx.fill();
},
_onMouseDown (e) {
e.preventDefault();
this.set('isClicking', true);
const coords = this._windowToCanvas(e.clientX, e.clientY);
this.set('lastPointX', coords.x);
this.set('lastPointY', coords.y);
},
_onMouseMove (e) {
e.preventDefault();
const canvasElement = this.get('canvasElement');
if (this.get('isClicking')) {
this._drawWindow();
const coords = this._windowToCanvas(e.clientX, e.clientY);
this._drawImage(canvasElement, coords.x, coords.y);
}
},
_onMouseUp (e) {
e.preventDefault();
this.set('isClicking', false);
},
_windowToCanvas (x, y) {
const canvas = this.get('canvasElement').getContext('2d').canvas;
const box = canvas.getBoundingClientRect()
return {
x: x - (box.left * (canvas.width / box.width)),
y: y - (box.top * (canvas.height / box.height)),
}
},
});
import Ember from 'ember';
export default Ember.Controller.extend({
});
body {
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
box-sizing: border-box;
margin: 0;
}
canvas {
border: 1px solid silver;
display: block;
cursor: move;
}
input[type="range"] {
margin: 20px auto;
display: block;
}
<canvas width=600 height=400></canvas>
<input type='range' min="0.2" max="1.2" step="0.05" value={{scale}} oninput={{action (mut scale) value="target.value"}}>
{
"version": "0.15.0",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.js",
"ember": "3.2.2",
"ember-template-compiler": "3.2.2",
"ember-testing": "3.2.2"
},
"addons": {
"ember-data": "3.2.0"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment