switched to Croppa

master
Maksim 2019-01-28 00:35:32 -08:00
rodzic 5e6789fc5c
commit b9ed1d6196
11 zmienionych plików z 100 dodań i 127 usunięć

14
package-lock.json wygenerowano
Wyświetl plik

@ -1622,6 +1622,11 @@
"integrity": "sha512-ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==", "integrity": "sha512-ogq4NbUWf1uG/j66k0AmiO3GjqJAlQyF8n4w8a954cbCyFKmYGvRtgz6qkq2fWuduTXHibX7GyYL5Pg58Aks2g==",
"dev": true "dev": true
}, },
"canvas-exif-orientation": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/canvas-exif-orientation/-/canvas-exif-orientation-0.4.0.tgz",
"integrity": "sha1-tIfzcBmYqeh56xBAELKlgRU2i2s="
},
"caseless": { "caseless": {
"version": "0.12.0", "version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
@ -10974,6 +10979,15 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-2.5.21.tgz", "resolved": "https://registry.npmjs.org/vue/-/vue-2.5.21.tgz",
"integrity": "sha512-Aejvyyfhn0zjVeLvXd70h4hrE4zZDx1wfZqia6ekkobLmUZ+vNFQer53B4fu0EjWBSiqApxPejzkO1Znt3joxQ==" "integrity": "sha512-Aejvyyfhn0zjVeLvXd70h4hrE4zZDx1wfZqia6ekkobLmUZ+vNFQer53B4fu0EjWBSiqApxPejzkO1Znt3joxQ=="
}, },
"vue-croppa": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/vue-croppa/-/vue-croppa-1.3.8.tgz",
"integrity": "sha512-WwYgEKscTCD7BzhnbfRJfzWIU6RcMq2JRimB3aI5gGzpADmpKuqmDh9+oVfiZaEnpmRthgXZxcAvbxU6CeIU9w==",
"requires": {
"canvas-exif-orientation": "^0.4.0",
"object-assign": "^4.1.1"
}
},
"vue-hot-reload-api": { "vue-hot-reload-api": {
"version": "2.3.1", "version": "2.3.1",
"resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz", "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.1.tgz",

Wyświetl plik

@ -39,6 +39,7 @@
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
"pica": "^5.0.0", "pica": "^5.0.0",
"vue": "^2.5.2", "vue": "^2.5.2",
"vue-croppa": "^1.3.8",
"vue-worker": "^1.2.1" "vue-worker": "^1.2.1"
}, },
"devDependencies": { "devDependencies": {

Wyświetl plik

@ -11,8 +11,8 @@
<image-chooser @selected="onInputSelected"></image-chooser> <image-chooser @selected="onInputSelected"></image-chooser>
<div class="image-upload" v-if="this.inputType === 'upload'"> <div class="image-upload" v-if="this.inputType === 'upload'">
<loader v-if="!cropper.loaded" ref="loader" :data="cropper"></loader> <croppa v-model="myCroppa" :width="250" :height="250" :preventWhiteSpace="true" :quality="2"></croppa>
<crop-actions v-if="cropper.loaded" :data="cropper" @change="change"></crop-actions> <button @click="uploadCroppedImage">Output JPEG</button>
</div> </div>
<div class="image-webcam" v-if="this.inputType === 'webcam'"> <div class="image-webcam" v-if="this.inputType === 'webcam'">
@ -102,24 +102,21 @@
</div> </div>
<div class="actions"> <div class="actions">
<button class="btn"> <button class="btn">
PNG JPG
</button> </button>
<button class="btn"> <button class="btn" @click="downloadSVG">
SVG SVG
</button> </button>
<button class="btn"> <button class="btn">
ZIP ZIP
</button> </button>
</div> </div>
<div class="panel-toggle">
<button id="panelToggler" class="btn"><span class="fa fa-chevron-left"></span></button>
</div>
</aside> </aside>
<main> <main>
<div v-if="canvasData" class="svg-container" style="padding: 10px;" ref="container"> <div v-if="canvasData" class="svg-container" style="padding: 10px;" ref="container">
<svg-chart :lines="lines" :options="line" :width="settings.width" :height="settings.height"></svg-chart> <svg-chart ref="svgResult" :lines="lines" :options="line" :width="settings.width" :height="settings.height"></svg-chart>
</div> </div>
<editor v-if="cropper.loaded" ref="editor" :data="cropper"></editor>
</main> </main>
</div> </div>
</div> </div>
@ -127,9 +124,9 @@
</template> </template>
<script> <script>
import Navbar from './components/Navbar' // import Navbar from './components/Navbar'
import Loader from './components/Loader' // import Loader from './components/Loader'
import Editor from './components/Editor' // import Editor from './components/Editor'
import ImageChooser from './components/ImageChooser' import ImageChooser from './components/ImageChooser'
import WebCam from './components/WebCam' import WebCam from './components/WebCam'
import svgChart from './components/svgChart'; import svgChart from './components/svgChart';
@ -137,15 +134,17 @@
export default { export default {
name: 'App', name: 'App',
components: { components: {
cropActions: Navbar , //cropActions: Navbar ,
loader: Loader, //loader: Loader,
editor: Editor, //editor: Editor,
imageChooser: ImageChooser, imageChooser: ImageChooser,
webcam: WebCam, webcam: WebCam,
svgChart: svgChart svgChart: svgChart
}, },
data() { data() {
return { return {
myCroppa: {},
dataUrl: '',
line: { line: {
smoothing: 0.25, smoothing: 0.25,
flattening: 0.5 flattening: 0.5
@ -173,16 +172,16 @@
devices: [], devices: [],
streaming: false streaming: false
}, },
cropper: { // cropper: {
cropped: false, // cropped: false,
cropping: false, // cropping: false,
loaded: false, // loaded: false,
name: '', // name: '',
previousUrl: '', // previousUrl: '',
type: '', // type: '',
url: '', // url: '',
croppedImageData: '' // croppedImageData: ''
}, // },
}; };
}, },
@ -198,12 +197,12 @@
this.webcam.deviceId = first.deviceId; this.webcam.deviceId = first.deviceId;
} }
}, },
'cropper.croppedImageData': function(){ // 'cropper.croppedImageData': function(){
const canvas = this.cropper.croppedImageData; // const canvas = this.cropper.croppedImageData;
const ctx = canvas.getContext("2d"); // const ctx = canvas.getContext("2d");
this.canvasData = ctx.getImageData(0, 0, 500, 500); // this.canvasData = ctx.getImageData(0, 0, 500, 500);
return true; // return true;
}, // },
'settings.frequency': function(){ 'settings.frequency': function(){
this.processImage(); this.processImage();
}, },
@ -219,6 +218,28 @@
}, },
methods: { methods: {
downloadSVG(){
console.log(this.$refs.svgResult.$el.innerHTML);
},
uploadCroppedImage() {
this.myCroppa.generateBlob((blob) => {
let canvas = document.createElement("canvas");
canvas.width = 500;
canvas.height = 500;
// const ctx = canvas.getContext("2d");
// this.canvasData = ctx.getImageData(0, 0, 500, 500);
const ctx = canvas.getContext('2d');
let img = new Image();
img.onload = () => {
ctx.drawImage(img, 0, 0)
this.canvasData = ctx.getImageData(0, 0, 500, 500);
};
img.src = URL.createObjectURL(blob);
}, 'image/jpeg', 1)
},
processImage() { processImage() {
this.$worker.run((data) => { this.$worker.run((data) => {
// Gather all necessary data from the main thread // Gather all necessary data from the main thread
@ -252,7 +273,7 @@
// starting pixel for each line will be this // starting pixel for each line will be this
// Loop through pixels from left to right within the current line, advancing by increments of config.SPACING // Loop through pixels from left to right within the current line, advancing by increments of config.SPACING
console.log(config.spacing, width); //console.log(config.spacing, width);
for (let x = config.spacing; x < width; x += config.spacing ) { for (let x = config.spacing; x < width; x += config.spacing ) {
currentHorizontalPixelIndex = x + currentVerticalPixelIndex; // Get array position of current pixel currentHorizontalPixelIndex = x + currentVerticalPixelIndex; // Get array position of current pixel
@ -358,21 +379,21 @@
<style lang="scss"> <style lang="scss">
@import './styles/index.scss'; @import './styles/index.scss';
.cropper-header { /*.cropper-header {*/
background-color: #666; /*background-color: #666;*/
height: 3rem; /*height: 3rem;*/
overflow: hidden; /*overflow: hidden;*/
padding-left: 1rem; /*padding-left: 1rem;*/
padding-right: 1rem; /*padding-right: 1rem;*/
position: relative; /*position: relative;*/
z-index: 1; /*z-index: 1;*/
} /*}*/
@media (min-width: 768px) { /*@media (min-width: 768px) {*/
.cropper-header { /*.cropper-header {*/
padding-left: 1.5rem; /*padding-left: 1.5rem;*/
padding-right: 1.5rem; /*padding-right: 1.5rem;*/
} /*}*/
} /*}*/
.title { .title {
color: #fff; color: #fff;
display: block; display: block;

Wyświetl plik

@ -3,7 +3,6 @@
<div class="button-group stretch"> <div class="button-group stretch">
<label>Input:</label> <label>Input:</label>
<button id="upload" :disabled="disabled" v-bind:class="{ active: selectedItem === 'upload' }" class="btn" @click="toggle">File</button> <button id="upload" :disabled="disabled" v-bind:class="{ active: selectedItem === 'upload' }" class="btn" @click="toggle">File</button>
<!--<button id="url" :disabled="disabled" v-bind:class="{ active: selectedItem === 'url' }" class="btn" @click="toggle">URL</button>-->
<button id="webcam" :disabled="disabled" class="btn" v-bind:class="{ active: selectedItem === 'webcam' }" @click="toggle">WebCam</button> <button id="webcam" :disabled="disabled" class="btn" v-bind:class="{ active: selectedItem === 'webcam' }" @click="toggle">WebCam</button>
</div> </div>
</div> </div>

Wyświetl plik

@ -1,13 +0,0 @@
<template>
</template>
<script>
export default {
name: "ImageTransformer"
}
</script>
<style scoped>
</style>

Wyświetl plik

@ -1,13 +0,0 @@
<template>
</template>
<script>
export default {
name: "SquiggleDataRetriever"
}
</script>
<style scoped>
</style>

Wyświetl plik

@ -1,13 +0,0 @@
<template>
</template>
<script>
export default {
name: "SquiggleRenderer"
}
</script>
<style scoped>
</style>

Wyświetl plik

@ -23,5 +23,9 @@
</script> </script>
<style scoped> <style scoped>
path {
fill: none;
stroke: #0f0f0f;
stroke-width: 1.5px;
}
</style> </style>

Wyświetl plik

@ -1,5 +1,5 @@
<template> <template>
<path :style="styles.path" :d="pathD"></path> <path :d="pathD"></path>
</template> </template>
<script> <script>
@ -9,15 +9,6 @@
name: "svgChartLine", name: "svgChartLine",
props: ["d", "o"], props: ["d", "o"],
computed: { computed: {
styles() {
return {
path: {
fill: 'none',
stroke: "#000",
strokeWidth: 1
}
};
},
pathD() { pathD() {
return this.pointsPositions.reduce((acc, e, i, a) => i === 0 return this.pointsPositions.reduce((acc, e, i, a) => i === 0
? `M ${e[0]},${e[1]}` ? `M ${e[0]},${e[1]}`
@ -45,20 +36,16 @@
const flat = lib.map(Math.cos(o.angle) * this.o.flattening, 0, 1, 1, 0) const flat = lib.map(Math.cos(o.angle) * this.o.flattening, 0, 1, 1, 0)
const angle = o.angle * flat + (reverse ? Math.PI : 0); const angle = o.angle * flat + (reverse ? Math.PI : 0);
const length = o.length * this.o.smoothing; const length = o.length * this.o.smoothing;
const x = current[0] + Math.cos(angle) * length; const x = Math.round((current[0] + Math.cos(angle) * length) * 100) / 100 ;
const y = current[1] + Math.sin(angle) * length; const y = Math.round((current[1] + Math.sin(angle) * length) * 100) / 100 ;
return [x, y]; return [x, y];
}, },
bezierCommand(point, i, a) { bezierCommand(point, i, a) {
const cps = this.controlPoint(a[i - 1], a[i - 2], point); const cps = this.controlPoint(a[i - 1], a[i - 2], point);
const cpe = this.controlPoint(point, a[i - 1], a[i + 1], true); const cpe = this.controlPoint(point, a[i - 1], a[i + 1], true);
//const close = i === a.length - 1 ? " z" : ""; //const close = i === a.length - 1 ? " z" : "";
return `C ${cps[0]},${cps[1]} ${cpe[0]},${cpe[1]} ${point[0]},${point[1]}`; return `C ${cps[0]},${cps[1]} ${cpe[0]},${cpe[1]} ${Math.round(point[0] * 100) / 100},${Math.round(point[1]*100)/100}`;
} }
} }
} }
</script> </script>
<style scoped>
</style>

Wyświetl plik

@ -4,13 +4,18 @@ import 'normalize.css'
import Vue from 'vue' import Vue from 'vue'
import App from './App' import App from './App'
import VueWorker from 'vue-worker'; import VueWorker from 'vue-worker';
import Croppa from 'vue-croppa'
//import './styles/index.scss' //import './styles/index.scss'
import 'cropperjs/dist/cropper.css'; //import 'cropperjs/dist/cropper.css';
Vue.config.productionTip = false import 'vue-croppa/dist/vue-croppa.css'
Vue.config.productionTip = false;
Vue.use(VueWorker); Vue.use(VueWorker);
Vue.use(Croppa);
/* eslint-disable no-new */ /* eslint-disable no-new */
@ -18,4 +23,4 @@ new Vue({
el: '#app', el: '#app',
components: { App }, components: { App },
template: '<App/>' template: '<App/>'
}) });

Wyświetl plik

@ -344,25 +344,6 @@ input[type="range"]:focus::-ms-fill-upper {
align-content: space-between; align-content: space-between;
} }
.panel-toggle {
position: absolute;
right: -12px;
bottom: 50px;
z-index: 1;
//align-self: center;
.btn {
z-index: 100;
background-color: #000;
padding: 20px 0;
}
.btn:hover {
color: #fff;
background-color: #0069d9;
border-color: #0062cc;
}
}
.image-webcam { .image-webcam {
position: relative; position: relative;