123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- <template>
- <div class="annotated-image" v-on="events">
- <img alt="media" ref="image" draggable="false"
- :src="mediaUrl" :srcset="mediaUrlSet" :sizes="mediaUrlSizes"/>
- <div style="position: absolute; top: 0.5rem; left: 0.5rem">{{ data }}</div>
- <annotation-box v-if="current"
- :image="image"
- :position="current"/>
- <annotation-box v-for="(result, index) in predictions"
- :type="result.origin"
- :key="index"
- :id="result.id"
- :image="image"
- :position="result"
- :socket="socket"
- :box-url="mediaUrl + '/' + result.id"
- @resize="resize"/>
- </div>
- </template>
- <script>
- import AnnotationBox from "@/components/media/annotation-box";
- export default {
- name: "annotated-image",
- components: {AnnotationBox},
- props: ['project', 'data', 'socket'],
- mounted: function () {
- window.addEventListener("resize", this.resizeEvent);
- if (this.$refs.image.complete)
- this.resizeEvent();
- else
- this.$refs.image.addEventListener('load', this.resizeEvent);
- },
- destroyed() {
- window.removeEventListener("resize", this.resizeEvent);
- },
- watch: {
- data: function () {
- this.current = false;
- this.resizeEvent();
- }
- },
- data: function () {
- return {
- sizes: [600, 800, 1200, 1600, 2000, 3000],
- image: {
- left: 0,
- top: 0,
- width: 0,
- height: 0
- },
- start: false,
- fixed: false,
- current: false,
- callback: false
- }
- },
- computed: {
- mediaUrl: function () {
- return this.socket.media(this.project.id, this.data.id);
- },
- mediaUrlSet: function () {
- return this.sizes.map(e => this.mediaUrl + '/' + e + ' ' + e + 'w').join(',');
- },
- mediaUrlSizes: function () {
- return this.sizes.map(e => '(max-width: ' + e + 'px) ' + e + 'px').join(',');
- },
- predictions: function () {
- return Object.keys(this.data.predictionResults).map(k => this.data.predictionResults[k]);
- },
- events: function () {
- return {
- 'touchstart': this.press,
- 'touchmove': this.track,
- 'touchend': this.release,
- 'mousedown': this.press,
- 'mousemove': this.track,
- 'mouseup': this.release,
- 'dragstart': e => e.stopPropagation()
- }
- }
- },
- methods: {
- resizeEvent: function () {
- const element = this.$refs.image.getBoundingClientRect();
- const parent = this.$refs.image.parentElement.getBoundingClientRect();
- this.image.left = element.x - parent.x;
- this.image.top = element.y - parent.y;
- this.image.width = element.width;
- this.image.height = element.height;
- },
- get: function (event) {
- if ('clientX' in event)
- return event;
- if ('touches' in event && event.touches.length > 0)
- return event.touches[0];
- if ('changedTouches' in event && event.changedTouches.length > 0)
- return event.changedTouches[0];
- },
- getX: function (event) {
- const bcr = this.$refs.image.getBoundingClientRect();
- return (this.get(event).clientX - bcr.left) / bcr.width;
- },
- getY: function (event) {
- const bcr = this.$refs.image.getBoundingClientRect();
- return (this.get(event).clientY - bcr.top) / bcr.height;
- },
- buildRectangle: function (x1, y1, x2, y2) {
- const lx = this.fixed && 'lx' in this.fixed ? this.fixed.lx : Math.max(Math.min(x1, x2), 0);
- const hx = this.fixed && 'hx' in this.fixed ? this.fixed.hx : Math.min(Math.max(x1, x2), 1);
- const ly = this.fixed && 'ly' in this.fixed ? this.fixed.ly : Math.max(Math.min(y1, y2), 0);
- const hy = this.fixed && 'hy' in this.fixed ? this.fixed.hy : Math.min(Math.max(y1, y2), 1);
- return {
- x: lx,
- y: ly,
- w: hx - lx,
- h: hy - ly
- }
- },
- press: function (event) {
- this.start = {
- x: this.getX(event),
- y: this.getY(event)
- };
- },
- track: function (event) {
- if (this.start) {
- const x = this.getX(event);
- const y = this.getY(event);
- this.current = this.buildRectangle(this.start.x, this.start.y, x, y);
- }
- },
- release: function () {
- if (this.start) {
- if (this.callback)
- this.callback(this.current);
- else
- this.socket.post(this.mediaUrl, this.current);
- this.start = false;
- this.fixed = false;
- this.current = false;
- this.callback = false;
- }
- },
- resize: function (position, mode, callback) {
- this.callback = callback;
- switch (mode) {
- case 'nw':
- this.start = {x: position.x + position.w, y: position.y + position.h};
- this.fixed = false;
- break;
- case 'ne':
- this.start = {x: position.x, y: position.y + position.h};
- this.fixed = false;
- break;
- case 'sw':
- this.start = {x: position.x + position.w, y: position.y};
- this.fixed = false;
- break;
- case 'se':
- this.start = {x: position.x, y: position.y};
- this.fixed = false;
- break;
- case 'nn':
- this.start = {x: position.x, y: position.y + position.h};
- this.fixed = {lx: position.x, hx: position.x + position.w};
- break;
- case 'ww':
- this.start = {x: position.x + position.w, y: position.y};
- this.fixed = {ly: position.y, hy: position.y + position.h};
- break;
- case 'ee':
- this.start = {x: position.x, y: position.y};
- this.fixed = {ly: position.y, hy: position.y + position.h};
- break;
- case 'ss':
- this.start = {x: position.x, y: position.y};
- this.fixed = {lx: position.x, hx: position.x + position.w};
- break;
- }
- }
- }
- }
- </script>
- <style scoped>
- img {
- max-width: 100%;
- max-height: 100%;
- }
- </style>
|