src_js/iconolab-bundle/src/components/editor/ZoomThumbnail.vue
changeset 335 86dbf2cdeeeb
child 355 004fdb42f063
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src_js/iconolab-bundle/src/components/editor/ZoomThumbnail.vue	Wed Feb 22 11:04:16 2017 +0100
@@ -0,0 +1,134 @@
+<template>
+    <div class="wrapper">
+        <svg ref="svg" v-bind:width="thumbnailWidth" v-bind:height="thumbnailHeight">
+            <image xmlns:xlink="http://www.w3.org/1999/xlink"
+                x="0" y="0"
+                v-bind:width="thumbnailWidth" v-bind:height="thumbnailHeight"
+                v-bind:xlink:href="image"></image>
+            <rect ref="handler"
+                class="move-handler"
+                v-bind:x="x" v-bind:y="y"
+                v-bind:width="width" v-bind:height="height"
+                style="fill: black; opacity: 0.4"></rect>
+        </svg>
+    </div>
+</template>
+
+<script>
+
+    import Snap from 'snapsvg'
+
+    export default {
+        props: [
+            'image',
+            'viewport',
+            'viewBox',
+            'imageWidth',
+            'imageHeight',
+        ],
+        data() {
+            return {
+                thumbnailWidth: 0,
+                thumbnailHeight: 0,
+                loaded: false
+            }
+        },
+        computed: {
+            x: function() {
+                return this.viewBox[0] * this.getRatioX();
+            },
+            y: function() {
+                return this.viewBox[1] * this.getRatioY();
+            },
+            width: function() {
+                return this.viewBox[2] * this.getRatioX();
+            },
+            height: function() {
+                return this.viewBox[3] * this.getRatioY();
+            }
+        },
+        methods: {
+            reset: function() {
+                var handler = new Snap(this.$refs.handler);
+                handler.node.removeAttribute('transform');
+            },
+            getRatioX: function() {
+                if (this.imageWidth === 0) { return 0; }
+
+                return this.thumbnailWidth / this.imageWidth;
+            },
+            getRatioY: function() {
+                if (this.imageHeight === 0) { return 0; }
+
+                return this.thumbnailHeight / this.imageHeight;
+            }
+        },
+        mounted() {
+
+            var svg = new Snap(this.$refs.svg);
+            var handler = new Snap(this.$refs.handler);
+
+            var img = new Image();
+            img.onload = (e) => {
+
+                var self = this;
+
+                svg.attr({
+                    viewBox: [0, 0, img.width, img.height]
+                });
+
+                Object.assign(this, {
+                    thumbnailWidth: img.width,
+                    thumbnailHeight: img.height,
+                    loaded: true
+                });
+
+                var events = {
+                    onMove: function (dx, dy, x, y) {
+
+                        var snapInvMatrix = this.transform().diffMatrix.invert();
+                        snapInvMatrix.e = snapInvMatrix.f = 0;
+                        var tdx = snapInvMatrix.x(dx, dy);
+                        var tdy = snapInvMatrix.y(dx, dy);
+
+                        var transformValue = this.data('origTransform') + (this.data('origTransform') ? "T" : "t") + [tdx, tdy];
+                        this.transform(transformValue);
+
+                        self.$emit('change', {
+                            x: this.getBBox().x * (self.imageWidth / self.thumbnailWidth),
+                            y: this.getBBox().y * (self.imageHeight / self.thumbnailHeight),
+                        });
+
+                    },
+                    onStart: function () {
+                        this.data('origTransform', this.transform().local);
+                        self.$emit('dragstart');
+                    },
+                    onEnd: function () {
+                        self.$emit('dragend');
+                    }
+                }
+
+                handler.drag(events.onMove, events.onStart, events.onEnd);
+            }
+
+            img.src = this.image;
+        }
+    }
+
+</script>
+
+<style scoped>
+.wrapper {
+    box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+.wrapper svg {
+    border: 2px solid black;
+    border-radius: 4px;
+}
+.move-handler {
+    cursor: -moz-grab;
+    cursor: -webkit-grab;
+    cursor: grab;
+}
+</style>