Skip to content

Commit

Permalink
fix vue 3
Browse files Browse the repository at this point in the history
  • Loading branch information
vunamhung committed Apr 26, 2021
1 parent 85ed7c3 commit 2a9abd3
Show file tree
Hide file tree
Showing 12 changed files with 15,774 additions and 322 deletions.
15,775 changes: 15,627 additions & 148 deletions package-lock.json

Large diffs are not rendered by default.

10 changes: 5 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "vue-konva",
"version": "2.1.7",
"name": "vue3-konva",
"version": "1.0.0",
"description": "Vue binding to canvas element via Konva framework",
"keywords": [
"vue",
Expand Down Expand Up @@ -53,13 +53,13 @@
"konva": ">3.2.5"
},
"devDependencies": {
"@vue/test-utils": "^1.0.0-beta.25",
"@vue/compiler-sfc": "^3.0.4",
"@vue/test-utils": "^2.0.0-beta.10",
"chai": "^4.2.0",
"konva": ">3.2.5",
"nwb": "^0.25.2",
"sinon": "^7.3.0",
"vue": "^2.6.11",
"vue-template-compiler": "^2.6.11"
"vue": "^3.0.11"
},
"engines": {
"node": ">= 4.0.0",
Expand Down
41 changes: 16 additions & 25 deletions src/components/KonvaNode.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import {
applyNodeProps,
findParentKonva,
createListener,
updatePicture,
konvaNodeMarker,
checkOrder,
} from '../utils';

import { h } from 'vue';
import { applyNodeProps, findParentKonva, updatePicture, konvaNodeMarker, checkOrder } from '../utils';
const EVENTS_NAMESPACE = '.vue-konva-event';

const CONTAINERS = {
Expand All @@ -21,11 +14,11 @@ export default function (nameNode) {
// Mark it to detect whether an Vue instance is KonvaNode or not later
[konvaNodeMarker]: true,

render(createElement) {
render() {
// containers should be able to draw children
const isContainer = CONTAINERS[nameNode];
if (isContainer) {
return createElement('template', this.$slots.default);
return h('template', this.$slots.default?.());
}
// other elements are not containers
return null;
Expand Down Expand Up @@ -54,25 +47,25 @@ export default function (nameNode) {
},
mounted() {
const parentVueInstance = findParentKonva(this);
const parentKonvaNode = parentVueInstance._konvaNode;
parentKonvaNode.add(this._konvaNode);
updatePicture(this._konvaNode);
const parentKonvaNode = parentVueInstance.__konvaNode;
parentKonvaNode.add(this.__konvaNode);
updatePicture(this.__konvaNode);
},
updated() {
this.uploadKonva();
checkOrder(this.$vnode, this._konvaNode);
checkOrder(this.$, this.__konvaNode);
},
destroyed() {
updatePicture(this._konvaNode);
this._konvaNode.destroy();
this._konvaNode.off(EVENTS_NAMESPACE);
unmounted() {
updatePicture(this.__konvaNode);
this.__konvaNode.destroy();
this.__konvaNode.off(EVENTS_NAMESPACE);
},
methods: {
getNode() {
return this._konvaNode;
return this.__konvaNode;
},
getStage() {
return this._konvaNode;
return this.__konvaNode;
},
initKonva() {
const NodeClass = window.Konva[nameNode];
Expand All @@ -82,17 +75,15 @@ export default function (nameNode) {
return;
}

this._konvaNode = new NodeClass();
this._konvaNode.VueComponent = this;

this.__konvaNode = new NodeClass();
this.$.vnode.__konvaNode = this.__konvaNode;
this.uploadKonva();
},
uploadKonva() {
const oldProps = this.oldProps || {};
const props = {
...this.$attrs,
...this.config,
...createListener(this.$listeners),
};
applyNodeProps(this, props, oldProps, this.__useStrictMode);
this.oldProps = props;
Expand Down
28 changes: 13 additions & 15 deletions src/components/Stage.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import Vue from 'vue';
import { applyNodeProps, createListener, checkOrder } from '../utils';
import { h } from 'vue';
import { applyNodeProps, checkOrder } from '../utils';

export default Vue.component('v-stage', {
render: function (createElement) {
return createElement('div', this.$slots.default);
export default {
render: function () {
return h('div', this.$slots.default?.());
},
watch: {
config: {
Expand All @@ -24,9 +24,8 @@ export default Vue.component('v-stage', {
type: Boolean,
},
},

created() {
this._konvaNode = new window.Konva.Stage({
this.__konvaNode = new window.Konva.Stage({
width: this.config.width,
height: this.config.height,
// create fake container, later it will be replaced with real div on the page
Expand All @@ -35,31 +34,30 @@ export default Vue.component('v-stage', {
},
mounted() {
this.$el.innerHTML = '';
this._konvaNode.container(this.$el);
this.__konvaNode.container(this.$el);
this.uploadKonva();
this.validateChildren();
},
updated() {
this.uploadKonva();
this.uploadKonva();
checkOrder(this.$vnode, this._konvaNode);
checkOrder(this.$, this.__konvaNode);
},
beforeDestroy() {
this._konvaNode.destroy();
beforeUnmount() {
this.__konvaNode.destroy();
},
methods: {
getNode() {
return this._konvaNode;
return this.__konvaNode;
},
getStage() {
return this._konvaNode;
return this.__konvaNode;
},
uploadKonva() {
const oldProps = this.oldProps || {};
const props = {
...this.$attrs,
...this.config,
...createListener(this.$listeners),
};
applyNodeProps(this, props, oldProps, this.__useStrictMode);
this.oldProps = props;
Expand All @@ -71,4 +69,4 @@ export default Vue.component('v-stage', {
// })
},
},
});
};
26 changes: 11 additions & 15 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,33 +28,29 @@ const KONVA_NODES = [
'RegularPolygon',
'Arrow',
'Shape',
'Transformer'
'Transformer',
];
const components = [
{
name: 'Stage',
component: Stage
component: Stage,
},
...KONVA_NODES.map(name => ({
...KONVA_NODES.map((name) => ({
name,
component: KonvaNode(name)
}))
component: KonvaNode(name),
})),
];

const VueKonva = {
install: (Vue, options) => {
install: (app, options) => {
let prefixToUse = componentPrefix;
if(options && options.prefix){
if (options && options.prefix) {
prefixToUse = options.prefix;
}
components.forEach(k => {
Vue.component(`${prefixToUse}${k.name}`, k.component);
})
}
components.forEach((k) => {
app.component(`${prefixToUse}${k.name}`, k.component);
});
},
};

export default VueKonva;

if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(VueKonva);
}
25 changes: 5 additions & 20 deletions src/utils/applyNodeProps.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,8 @@ import updatePicture from './updatePicture';
const propsToSkip = { key: true, style: true, elm: true, isRootInsert: true };
const EVENTS_NAMESPACE = '.vue-konva-event';

export default function applyNodeProps(
vueComponent,
props = {},
oldProps = {},
useStrict
) {
const instance = vueComponent._konvaNode;
export default function applyNodeProps(vueComponent, props = {}, oldProps = {}, useStrict) {
const instance = vueComponent.__konvaNode;
var updatedProps = {};
var hasUpdates = false;
for (let key in oldProps) {
Expand All @@ -23,10 +18,7 @@ export default function applyNodeProps(
if (isEvent && propChanged) {
var eventName = key.substr(2).toLowerCase();
if (eventName.substr(0, 7) === 'content') {
eventName =
'content' +
eventName.substr(7, 1).toUpperCase() +
eventName.substr(8);
eventName = 'content' + eventName.substr(7, 1).toUpperCase() + eventName.substr(8);
}
instance.off(eventName + EVENTS_NAMESPACE, oldProps[key]);
}
Expand All @@ -44,21 +36,14 @@ export default function applyNodeProps(
if (isEvent && toAdd) {
let eventName = key.substr(2).toLowerCase();
if (eventName.substr(0, 7) === 'content') {
eventName =
'content' +
eventName.substr(7, 1).toUpperCase() +
eventName.substr(8);
eventName = 'content' + eventName.substr(7, 1).toUpperCase() + eventName.substr(8);
}
if (props[key]) {
instance.off(eventName + EVENTS_NAMESPACE);
instance.on(eventName + EVENTS_NAMESPACE, props[key]);
}
}
if (
!isEvent &&
(props[key] !== oldProps[key] ||
(useStrict && props[key] !== instance.getAttr(key)))
) {
if (!isEvent && (props[key] !== oldProps[key] || (useStrict && props[key] !== instance.getAttr(key)))) {
hasUpdates = true;
updatedProps[key] = props[key];
}
Expand Down
51 changes: 25 additions & 26 deletions src/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@ export function copy(obj) {
return JSON.parse(JSON.stringify(obj));
}

export function createListener(obj) {
const output = {};
Object.keys(obj).forEach((eventName) => {
output['on' + eventName] = obj[eventName];
});
return output;
}

export function findParentKonva(instance) {
function re(instance) {
if (instance._konvaNode) {
if (instance.__konvaNode) {
return instance;
}
if (instance.$parent) {
Expand All @@ -30,39 +22,46 @@ export function findParentKonva(instance) {
}

export function findKonvaNode(instance) {
if (!instance) {
if (!instance?.component?.ctx) {
return null;
}
if (instance.$options[konvaNodeMarker]) {
return instance.getNode();
if (instance?.component?.ctx?.__konvaNode) {
return instance.component.ctx.__konvaNode;
}
if (instance.$children.length === 0) {
return null;
if (instance.component.subTree.__konvaNode) {
return instance.component.subTree.__konvaNode;
}
return findKonvaNode(instance.$children[0]);
return findKonvaNode(instance.component.subTree);
}

export function checkOrder($vnode, konvaNode) {
export function checkOrder($, konvaNode) {
let needRedraw = false;
// check indexes
// somehow this.$children are not ordered correctly
// so we have to dive-in into componentOptions of vnode
// also componentOptions.children may have empty nodes, and other non Konva elements so we need to filter them first

const children = $vnode.componentOptions.children || [];
let children = [];

if ($.subTree.children) {
$.subTree.children.forEach((child) => {
if (!child.component && Array.isArray(child.children)) {
children.push(...child.children);
}
if (child.component) {
children.push(child);
}
});
}

const nodes = [];
children.forEach(($vnode) => {
const konvaNode = findKonvaNode($vnode.componentInstance);
const konvaNode = findKonvaNode($vnode);
if (konvaNode) {
nodes.push(konvaNode);
}

const { elm, componentInstance } = $vnode;
if (elm && elm.tagName && componentInstance && !konvaNode) {
const name = elm && elm.tagName.toLowerCase();
const { el, component } = $vnode;
if (el && el.tagName && component && !konvaNode) {
const name = el && el.tagName.toLowerCase();
console.error(
`vue-konva error: You are trying to render "${name}" inside your component tree. Looks like it is not a Konva node. You can render only Konva components inside the Stage.`
`vue-konva error: You are trying to render "${name}" inside your component tree. Looks like it is not a Konva node. You can render only Konva components inside the Stage.`,
);
}
});
Expand Down
6 changes: 0 additions & 6 deletions umd/vue-konva.min.js

This file was deleted.

1 change: 0 additions & 1 deletion umd/vue-konva.min.js.map

This file was deleted.

Loading

0 comments on commit 2a9abd3

Please sign in to comment.