GithubHelp home page GithubHelp logo

drsensor / vue-annotator Goto Github PK

View Code? Open in Web Editor NEW
79.0 4.0 16.0 97 KB

Vue Component for drawing annotation (rect, polygon, etc) using SVG element

Home Page: http://vue-annotator.surge.sh

License: MIT License

JavaScript 53.52% Vue 46.48%
annotations svg vue-annotator vue-components vue my-amusement

vue-annotator's Introduction

vue-annotator CircleCI

npm npm donate

Create annotation using SVG and HTML element.

Usage

For complete example see src/stories/*/*.vue

<v-annotator inertia
  :drawing="enableDrawingMode"
  @select="openDialog"
  :minSize="[50, 50]"
  :grid="[5, 5]"
  :multipleSelect="keyIsDown.Ctrl"
>

    <img draggable="false" src="background.png" />

    <rect slot="annotation" stroke="green" x="300" y="150" width="170" height="100" />
    <polygon slot="annotation" stroke="purple" points="200,10 250,190 160,210" />

    <rect slot="drawing" stroke="red" />

</v-annotator>
<style scoped>
@import '~vue-annotator/style.css';

/* Your beloved style */
</style>
Enable --skipLibCheck if using typescript

Due to taye/interact.js#623

In tsconfig.json

{
  compilerOptions: {
    skipLibCheck: true
  }
}

Now it should work fine

import { Vue, Component } from 'vue-property-decorator'
import VAnnotator from 'vue-annotator'

@Component({ components: { VAnnotator } })
export class MyCanvas extends Vue {
  /** Your beloved logic */
}

API References

Props

* : must be set if no background

Parameters Description Type Must Specify Default value
width width of drawing canvas Number *optional width of background
height width of drawing canvas Number *optional height of background
grid set grid for snapping. :grid="[w,h]" for setting width and height. :grid="w" for setting grid in square Array[2] or Number optional null
min-size set minimum size of annotation. :minSize="[w,h]" for set minimum width and height of annotation size. :grid="w" for set minimum width and height of annotation size equal to w Array[2] or Number optional false
drawing switch to drawing mode Boolean optional false
inertia enable inertia moment animation when interacting Boolean optional false
multiple-select enable multiple select Boolean optional false
mouse-select restrict select only for specific mouse button String of left|right|middle optional
delete.sync delete selected element when set to true Boolean optional

Slots

* : will error when more than 1 element to be provided

Method name Description Accepted Element
default background element of annotation Any HTML element
annotation annotation element (accept SVG element) <rect>, <ellipse>, <circle>, <polygon>, <path>, <foreignObject>
drawing *draw element via mouse click&drag <rect>, <ellipse>, <circle>

Events

Event name Description Parameters
select emit when element is click/select element: SVG.Element
select-left emit when element is clicked with left mouse button element: SVG.Element
select-middle emit when element is clicked with middle mouse button element: SVG.Element
select-right emit when element is clicked with right mouse button element: SVG.Element
unselect emit when element is unselected (by clicking the background) element: SVG.Element
move emit when element is moved element: SVG.Element
move-end emit after the element is moved element: SVG.Element
resize emit when element is resized element: SVG.Element
resize-end emit after the element is resized element: SVG.Element
draw emit when drawing an element element: SVG.Element
draw-end emit when drawing element is finish element: SVG.Element
draw-cancel emit when drawing element is canceled (via right click)
update:delete emit when shape was successfully deleted

Tips: use element.node.isSameNode(this.$refs.myAnnotation) for identifying the element.

Style CSS

Vue-Annotator use svg.select.js

Class name Description Notes
.svg_select_boundingRect define style of rectangle in selected element only applicable on <rect>, <circle>, <ellipse>
.svg_select_points define style of edge circles in selected element

default style

.svg_select_points {
  stroke-width: 1;
  fill: black;
  stroke-dasharray: 10 10;
  stroke: black;
  stroke-opacity: 0.8;
  pointer-events: none; /* This ons is needed if you want to deselect or drag the shape*/
}

.svg_select_boundingRect {
  display: none;
}

Support

See CONTRIBUTING.md for contributing directly via:

License

MIT License

vue-annotator's People

Contributors

drsensor avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

vue-annotator's Issues

Line spacing is too wide

Right now it looks like each line is too wide apart, how can I make them closer to improve readability?

[Ask] alternative to this library/component?

Anyone know a framework agnostics annotation using SVG element that has a similar mechanism (using slot or others) like vue-annotator (this lib)?

Or at least framework specifics! I'm thinking to do some survey and see if it's worth remaking this library 🤔

Add event listener for delete and option for enable delete

Related to #5, add feature for doing delete operation.

<img v-if="!deleted" src="delete_me_senpai.png" />

<annotator enable-delete
  @delete="element  => deleted = element.node.isSameNode(this.$refs.red)"
>
   <rect ref="red" stroke="red" x="45" y="23" width="100" height="120" />
</annotator>

Reduce code complexity

Use mixins or extends to spearate logic of interaction. By doing this it can make annotator not only based on svg, but also HTML tag inside div or even 3d xml/component like a-frame or x3dom.

[BUG]: only last SVG shape interactable when in use with ApolloQuery component

How to reproduce

  <ApolloQuery ref="apollo" :query="require('@/types/Annotation.gql').GetEThing" :variables="{ id }" @result="({data}) => ething = data.eThing">

    <template slot-scope="{ result: { loading, error } }">
      <v-annotator ref="annotator" v-bind="$attrs" v-on="$listeners" @drawfinish="onDrawFinish">
        <img draggable="false" :src="ething.url" />

        <template v-if="!loading" slot="annotation" v-for="({dimension,shape}, i) in ething.annotations" >
          <rect class="annotation" v-if="is(shape,'rect')" :x="dimension[0]" :y="dimension[1]" :width="dimension[2]" :height="dimension[3]" :key="i" />
        </template>

      </v-annotator>
    </template>
  </ApolloQuery>

[Props]: Add mock-draw

Similiar to draw prop but it only mock (only do the drawing animation), doesn't create the annotation. (doesn't clone-append to <g>...</g> when @drawFinish)
Useful if you want to control how the annotation is created.

In my case the creation depends on query result from ApolloQuery component)

Usage

<v-annotator mock-draw>

  <template v-for="({x, y, w, h, shape}, index) in onQueryUpdate(dataFromSlotScope)">

    <rect v-if="shape === 'rect'" :x="x" :y="y" :width="w" :height="h" :key="index" />
    <circle v-else-if="shape === 'circle'" :cx="x" :cy="y" :r="(w+h)/2" :key="index" />

  </template>

  <rect slot="drawing" />
</v-annotator>

How can I use this project ?

Hi I m new to Vuejs and I installed the project using the npm install command. I used Vue.use(require('vue-annotator')) to add the package to my project into my main.js.

However when I use the example of the Readme I get this error:
Unknown custom element: <v-annotator> - did you register the component correctly? For recursive components, make sure to provide the "name" option.
why isn't Vue recognizing the component?

Couldn’t move object

followed the console error:

interact.js?fb3a:8321 Uncaught TypeError: Cannot read property '0' of undefined
    at Object.__set_38 [as set] (interact.js?fb3a:8321)
    at setAll (interact.js?fb3a:7121)
    at __beforeMove_30 (interact.js?fb3a:7147)
    at Signals.fire (interact.js?fb3a:2762)
    at Interaction._doPhase (interact.js?fb3a:1144)
    at Interaction.move (interact.js?fb3a:925)
    at Interaction.pointerMove (interact.js?fb3a:887)
    at HTMLDocument.eval (interact.js?fb3a:566)

Add @move listener

Emit move event with SVG.Element as emitted value when moving the annotation.
The event is emitted after the movement is finish.
The use case is when you want to save/send/sync the coordinate of the annotation.

Usage

<v-annotation @move="el => $http.post('/a/1', [ el.x(), el.y(), el.width(), el.height() ])" >

Subscribe to an existing mqtt broker

In FileViewer.vue, use Vue-mqtt for subscribing to mqtt topic when annotation is selected or Listener mod is on.

  • add switch button for activating listener mode.
  • implement <v-annotator v-on:select="subscribe" ... for subscribe to mqtt topic when shape is selected.
  • add additional navbar tab for list available mqtt topic in <v-table>

Create global css for `select shape` functionality

This enhancement is to avoid a need to

<style>
import url('~vue-annotator/dist/vue-annotator.css')
</style>

when using this component.

Create global css for .svg_* class at beforeCreate. Follow this https://gomakethings.com/two-ways-to-set-an-elements-css-with-vanilla-javascript/#approach-2-adding-global-styles articles and don't forget to make it called only once (use global var to do that).

In src/components/Annonator.vue

let callOnce = false

export default {
. 
. 
. 
  beforeCreate () {
    if (!callOnce) {
       // code to add global css
       callOnce = true
    } 
  }
} 

problem with drawing slot

Hello guys. When i use the slot="annotation" on the rect element the annotation doesnt go out of the canvas border. Furthermore the annotation doesn't move faster than my mouse cursor when selected. On the other hand the annotation i create my self with slot="drawing" on the rect element move way faster than my mouse cursor and they go outside the borders. Can anyone help me understand why this is happening?

<rect class="stroke" slot="drawing" />

<rect class="stroke" slot="annotation" x="100" y="100" width="100" height="100" />

Add unselect event

This is usefull if you have a case like this:

<button @click="deleteMode = true">delete mode on</button>

<annotator 
    :enable-delete="deleteMode" 
    @unselect="deleteMode = false"
>
      <rect class="annotation-box" slot="drawing" />
      <polygon class="annotation-box" slot="annotation" points="200,10 250,190 160,210" />
      <rect class="annotation-box" slot="annotation" x="300" y="150" width="170" height="100" />
      <ImageViewer :source="openedFile.uri" />
</annotator>

Apply texture when annotation is selected

Slots

Method name Description Accepted Element
select *texture element to apply when annotation is selected <defs>

Usage

  <defs slot="select">
    <linearGradient id="Gradient01">
      <stop offset="20%" stop-color="#39F" />
      <stop offset="90%" stop-color="#F3F" />
    </linearGradient>
  </defs>

run event select after event @draw-end="createRect"

Hi, I have problem with run methods after methods

createRect() {
      const canvas = this.$refs.canvas;
      const eIsSameNode = e.node.isSameNode(canvas);
      this.$refs.canvas._events.select(eIsSameNode);
}

Now:
image

I need to create new rect element and just now select this:

image

Make basic operation become 2 way data binding

Make this events able v-bind by invoking <op>.sync

  • :select.sync="element"
  • :unselect.sync="element"
  • :delete.sync="element"
  • :add.sync="element"

Tips: use watch: { <op>: val => operation() } to listen when the props changed (assigned)

BUG: shape not interact able at first draw in drawing mode

When slot annotation is empty, the shape after the first draw the shape disappear and not show in the HTML doc. However, at 2nd draw its success, the shape is drawn but it cannot be interacted (select, drag, draw).

<annotation drawing :width="600" :height="600">
  <rect slot="drawing" />
</annotation>

BUG: polygon not unselected when clicking background

    <annotator inertia :drawing="annotateMode.add" @select="editAnnotation" @drawdone="addAnnotation">
      <rect class="annotation-box" slot="drawing" />
      <polygon class="annotation-box" slot="annotation" points="200,10 250,190 160,210" />
      <rect class="annotation-box" slot="annotation" x="300" y="150" width="170" height="100" />
      <ImageViewer :source="openedFile.uri" />
    </annotator>

Add event when shape intersect with each other

Emit intersect event every time shape intersect with each others. Each intersect will emit data array of SVG.Element

  • @intersect.start when shape begin to intersect
  • @intersect.end when shape leave intersection
  • @intersect fire continously each time shape move and intersect.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.