modal class not working on buttons - javascript

I have this form.
<form action="../massmail.php" method="post">
<label>Periode:</label>
<div class="form-inline"><input class="form-inline input-small" name="maand" type="text" placeholder="bijv.: juni" />
<input class="input-mini" name="jaar" type="text" value="2015" />
</div>
<br /> <label>Inleidende tekst:</label>
<div>
<textarea name="inleiding" rows="5"></textarea>
</div>
<br /> <label>url van de nieuwsbrief:</label>
<div>
<input class="input-xxlarge" name="link" type="url" value="" />
</div>
<div class="form-actions">
<button class="btn btn-primary" type="submit">Verzenden</button>
<button class="btn" formaction="../voorbeeld.php" formmethod="get" type="submit">Voorbeeld</button>
<button class="btn" type="button">Annuleren</button> </div>
</form>
In the last <div> are the form controlls. The second button is what I want to change. It submits the form, overriding the default form action and gives a preview of what would be sent if the actual submit button (Verzenden) is pressed.
This all works, but I want to give this preview in a modal window (pop up). For some reason the modal class only works for <a> elements. I have previously solved this by setting the <a> element class to btn modal, but in this case I need the formaction so I need an actual button.
Things I have tried and results.
<button class="btn modal" formaction="../voorbeeld.php" formmethod="get" type="submit" rel="{handler: 'iframe', size: {x: 920, y: 530}}">Voorbeeld</button>
Result: Form get's handled the way I expect, but no popup, results just get displayed as if a link is opened to the php page.
<a class="modal" href="voorbeeld.php" rel="{handler: 'iframe', size: {x: 920, y: 530}}"> <button class="btn" type="button" formaction="../voorbeeld.php" formmethod="get" type="submit">Voorbeeld MOD</button> </a>
Result: This opens the popup with the php page, but the results from the form don't get through to the php page.
Included as snippet is the modal.css, which doesn't seem to have anything <a> or <button> specific. modal.js is the javascript, but I'm not really familiar with that.
I'm doing all of this in a custom html module in Joomla! 3.4.3.
Any help would be appreciated
/*
MIT-style license
#author Harald Kirschner <mail [at] digitarald.de>
#author Rouven Weßling <me [at] rouvenwessling.de>
#copyright Author
*/
var SqueezeBox = {
presets: {
onOpen: function() {},
onClose: function() {},
onUpdate: function() {},
onResize: function() {},
onMove: function() {},
onShow: function() {},
onHide: function() {},
size: {
x: 600,
y: 450
},
sizeLoading: {
x: 200,
y: 150
},
marginInner: {
x: 20,
y: 20
},
marginImage: {
x: 50,
y: 75
},
handler: false,
target: null,
closable: true,
closeBtn: true,
zIndex: 65555,
overlayOpacity: .7,
classWindow: "",
classOverlay: "",
overlayFx: {},
resizeFx: {},
contentFx: {},
parse: false,
parseSecure: false,
shadow: true,
overlay: true,
document: null,
ajaxOptions: {}
},
initialize: function(e) {
if (this.options) return this;
this.presets = Object.merge(this.presets, e);
this.doc = this.presets.document || document;
this.options = {};
this.setOptions(this.presets).build();
this.bound = {
window: this.reposition.bind(this, [null]),
scroll: this.checkTarget.bind(this),
close: this.close.bind(this),
key: this.onKey.bind(this)
};
this.isOpen = this.isLoading = false;
return this
},
build: function() {
this.overlay = new Element("div", {
id: "sbox-overlay",
"aria-hidden": "true",
styles: {
zIndex: this.options.zIndex
},
tabindex: -1
});
this.win = new Element("div", {
id: "sbox-window",
role: "dialog",
"aria-hidden": "true",
styles: {
zIndex: this.options.zIndex + 2
}
});
if (this.options.shadow) {
if (Browser.chrome || Browser.safari && Browser.version >= 3 || Browser.opera && Browser.version >= 10.5 || Browser.firefox && Browser.version >= 3.5 || Browser.ie && Browser.version >= 9) {
this.win.addClass("shadow")
} else if (!Browser.ie6) {
var e = (new Element("div", {
"class": "sbox-bg-wrap"
})).inject(this.win);
var t = function(e) {
this.overlay.fireEvent("click", [e])
}.bind(this);
["n", "ne", "e", "se", "s", "sw", "w", "nw"].each(function(n) {
(new Element("div", {
"class": "sbox-bg sbox-bg-" + n
})).inject(e).addEvent("click", t)
})
}
}
this.content = (new Element("div", {
id: "sbox-content"
})).inject(this.win);
this.closeBtn = (new Element("a", {
id: "sbox-btn-close",
href: "#",
role: "button"
})).inject(this.win);
this.closeBtn.setProperty("aria-controls", "sbox-window");
this.fx = {
overlay: (new Fx.Tween(this.overlay, Object.merge({
property: "opacity",
onStart: Events.prototype.clearChain,
duration: 250,
link: "cancel"
}, this.options.overlayFx))).set(0),
win: new Fx.Morph(this.win, Object.merge({
onStart: Events.prototype.clearChain,
unit: "px",
duration: 750,
transition: Fx.Transitions.Quint.easeOut,
link: "cancel",
unit: "px"
}, this.options.resizeFx)),
content: (new Fx.Tween(this.content, Object.merge({
property: "opacity",
duration: 250,
link: "cancel"
}, this.options.contentFx))).set(0)
};
document.id(this.doc.body).adopt(this.overlay, this.win)
},
assign: function(e, t) {
return (document.id(e) || $$(e)).addEvent("click", function() {
return !SqueezeBox.fromElement(this, t)
})
},
open: function(e, t) {
this.initialize();
if (this.element != null) this.trash();
this.element = document.id(e) || false;
this.setOptions(Object.merge(this.presets, t || {}));
if (this.element && this.options.parse) {
var n = this.element.getProperty(this.options.parse);
if (n && (n = JSON.decode(n, this.options.parseSecure))) this.setOptions(n)
}
this.url = (this.element ? this.element.get("href") : e) || this.options.url || "";
this.assignOptions();
var r = r || this.options.handler;
if (r) return this.setContent(r, this.parsers[r].call(this, true));
var i = false;
return this.parsers.some(function(e, t) {
var n = e.call(this);
if (n) {
i = this.setContent(t, n);
return true
}
return false
}, this)
},
fromElement: function(e, t) {
return this.open(e, t)
},
assignOptions: function() {
this.overlay.addClass(this.options.classOverlay);
this.win.addClass(this.options.classWindow)
},
close: function(e) {
var t = typeOf(e) == "domevent";
if (t) e.stop();
if (!this.isOpen || t && !Function.from(this.options.closable).call(this, e)) return this;
this.fx.overlay.start(0).chain(this.toggleOverlay.bind(this));
this.win.setProperty("aria-hidden", "true");
this.fireEvent("onClose", [this.content]);
this.trash();
this.toggleListeners();
this.isOpen = false;
return this
},
trash: function() {
this.element = this.asset = null;
this.content.empty();
this.options = {};
this.removeEvents().setOptions(this.presets).callChain()
},
onError: function() {
this.asset = null;
this.setContent("string", this.options.errorMsg || "An error occurred")
},
setContent: function(e, t) {
if (!this.handlers[e]) return false;
this.content.className = "sbox-content-" + e;
this.applyTimer = this.applyContent.delay(this.fx.overlay.options.duration, this, this.handlers[e].call(this, t));
if (this.overlay.retrieve("opacity")) return this;
this.toggleOverlay(true);
this.fx.overlay.start(this.options.overlayOpacity);
return this.reposition()
},
applyContent: function(e, t) {
if (!this.isOpen && !this.applyTimer) return;
this.applyTimer = clearTimeout(this.applyTimer);
this.hideContent();
if (!e) {
this.toggleLoading(true)
} else {
if (this.isLoading) this.toggleLoading(false);
this.fireEvent("onUpdate", [this.content], 20)
} if (e) {
if (["string", "array"].contains(typeOf(e))) {
this.content.set("html", e)
} else {
this.content.adopt(e)
}
}
this.callChain();
if (!this.isOpen) {
this.toggleListeners(true);
this.resize(t, true);
this.isOpen = true;
this.win.setProperty("aria-hidden", "false");
this.fireEvent("onOpen", [this.content])
} else {
this.resize(t)
}
},
resize: function(e, t) {
this.showTimer = clearTimeout(this.showTimer || null);
var n = this.doc.getSize(),
r = this.doc.getScroll();
this.size = Object.merge(this.isLoading ? this.options.sizeLoading : this.options.size, e);
var i = self.getSize();
if (this.size.x == i.x) {
this.size.y = this.size.y - 50;
this.size.x = this.size.x - 20
}
if (n.x > 979) {
var s = {
width: this.size.x,
height: this.size.y,
left: (r.x + (n.x - this.size.x - this.options.marginInner.x) / 2).toInt(),
top: (r.y + (n.y - this.size.y - this.options.marginInner.y) / 2).toInt()
}
} else {
var s = {
width: n.x - 40,
height: n.y,
left: (r.x + 10).toInt(),
top: (r.y + 20).toInt()
}
}
this.hideContent();
if (!t) {
this.fx.win.start(s).chain(this.showContent.bind(this))
} else {
this.win.setStyles(s);
this.showTimer = this.showContent.delay(50, this)
}
return this.reposition()
},
toggleListeners: function(e) {
var t = e ? "addEvent" : "removeEvent";
this.closeBtn[t]("click", this.bound.close);
this.overlay[t]("click", this.bound.close);
this.doc[t]("keydown", this.bound.key)[t]("mousewheel", this.bound.scroll);
this.doc.getWindow()[t]("resize", this.bound.window)[t]("scroll", this.bound.window)
},
toggleLoading: function(e) {
this.isLoading = e;
this.win[e ? "addClass" : "removeClass"]("sbox-loading");
if (e) {
this.win.setProperty("aria-busy", e);
this.fireEvent("onLoading", [this.win])
}
},
toggleOverlay: function(e) {
if (this.options.overlay) {
var t = this.doc.getSize().x;
this.overlay.set("aria-hidden", e ? "false" : "true");
this.doc.body[e ? "addClass" : "removeClass"]("body-overlayed");
if (e) {
this.scrollOffset = this.doc.getWindow().getSize().x - t
} else {
this.doc.body.setStyle("margin-right", "")
}
}
},
showContent: function() {
if (this.content.get("opacity")) this.fireEvent("onShow", [this.win]);
this.fx.content.start(1)
},
hideContent: function() {
if (!this.content.get("opacity")) this.fireEvent("onHide", [this.win]);
this.fx.content.cancel().set(0)
},
onKey: function(e) {
switch (e.key) {
case "esc":
this.close(e);
case "up":
case "down":
return false
}
},
checkTarget: function(e) {
return e.target !== this.content && this.content.contains(e.target)
},
reposition: function() {
var e = this.doc.getSize(),
t = this.doc.getScroll(),
n = this.doc.getScrollSize();
var r = this.overlay.getStyles("height");
var i = parseInt(r.height);
if (n.y > i && e.y >= i) {
this.overlay.setStyles({
width: n.x + "px",
height: n.y + "px"
});
this.win.setStyles({
left: (t.x + (e.x - this.win.offsetWidth) / 2 - this.scrollOffset).toInt() + "px",
top: (t.y + (e.y - this.win.offsetHeight) / 2).toInt() + "px"
})
}
return this.fireEvent("onMove", [this.overlay, this.win])
},
removeEvents: function(e) {
if (!this.$events) return this;
if (!e) this.$events = null;
else if (this.$events[e]) this.$events[e] = null;
return this
},
extend: function(e) {
return Object.append(this, e)
},
handlers: new Hash,
parsers: new Hash
};
SqueezeBox.extend(new Events(function() {})).extend(new Options(function() {})).extend(new Chain(function() {}));
SqueezeBox.parsers.extend({
image: function(e) {
return e || /\.(?:jpg|png|gif)$/i.test(this.url) ? this.url : false
},
clone: function(e) {
if (document.id(this.options.target)) return document.id(this.options.target);
if (this.element && !this.element.parentNode) return this.element;
var t = this.url.match(/#([\w-]+)$/);
return t ? document.id(t[1]) : e ? this.element : false
},
ajax: function(e) {
return e || this.url && !/^(?:javascript|#)/i.test(this.url) ? this.url : false
},
iframe: function(e) {
return e || this.url ? this.url : false
},
string: function(e) {
return true
}
});
SqueezeBox.handlers.extend({
image: function(e) {
var t, n = new Image;
this.asset = null;
n.onload = n.onabort = n.onerror = function() {
n.onload = n.onabort = n.onerror = null;
if (!n.width) {
this.onError.delay(10, this);
return
}
var e = this.doc.getSize();
e.x -= this.options.marginImage.x;
e.y -= this.options.marginImage.y;
t = {
x: n.width,
y: n.height
};
for (var r = 2; r--;) {
if (t.x > e.x) {
t.y *= e.x / t.x;
t.x = e.x
} else if (t.y > e.y) {
t.x *= e.y / t.y;
t.y = e.y
}
}
t.x = t.x.toInt();
t.y = t.y.toInt();
this.asset = document.id(n);
n = null;
this.asset.width = t.x;
this.asset.height = t.y;
this.applyContent(this.asset, t)
}.bind(this);
n.src = e;
if (n && n.onload && n.complete) n.onload();
return this.asset ? [this.asset, t] : null
},
clone: function(e) {
if (e) return e.clone();
return this.onError()
},
adopt: function(e) {
if (e) return e;
return this.onError()
},
ajax: function(e) {
var t = this.options.ajaxOptions || {};
this.asset = (new Request.HTML(Object.merge({
method: "get",
evalScripts: false
}, this.options.ajaxOptions))).addEvents({
onSuccess: function(e) {
this.applyContent(e);
if (t.evalScripts !== null && !t.evalScripts) Browser.exec(this.asset.response.javascript);
this.fireEvent("onAjax", [e, this.asset]);
this.asset = null
}.bind(this),
onFailure: this.onError.bind(this)
});
this.asset.send.delay(10, this.asset, [{
url: e
}])
},
iframe: function(e) {
var t = this.doc.getSize();
if (t.x > 979) {
var n = this.options.size.x;
var r = this.options.size.y
} else {
var n = t.x;
var r = t.y - 50
}
this.asset = new Element("iframe", Object.merge({
src: e,
frameBorder: 0,
width: n,
height: r
}, this.options.iframeOptions));
if (this.options.iframePreload) {
this.asset.addEvent("load", function() {
this.applyContent(this.asset.setStyle("display", ""))
}.bind(this));
this.asset.setStyle("display", "none").inject(this.content);
return false
}
return this.asset
},
string: function(e) {
return e
}
});
SqueezeBox.handlers.url = SqueezeBox.handlers.ajax;
SqueezeBox.parsers.url = SqueezeBox.parsers.ajax;
SqueezeBox.parsers.adopt = SqueezeBox.parsers.clone;
/**
* SqueezeBox - Expandable Lightbox
*
* Allows to open various content as modal,
* centered and animated box.
*
* #version 1.3
*
* #license MIT-style license
* #author Harald Kirschner <mail [at] digitarald.de>
* #author Rouven Weßling <me [at] rouvenwessling.de>
* #copyright Author
*/
#sbox-overlay {
position: absolute;
background-color: #000;
left: 0px;
top: 0px;
}
#sbox-window {
position: absolute;
background-color: #fff;
text-align: left;
overflow: visible;
padding: 10px;
/* invalid values, but looks smoother! */
-moz-border-radius: 3px;
-webkit-border-radius: 3px;
border-radius: 3px;
}
#sbox-window[aria-hidden=true],
#sbox-overlay[aria-hidden=true] {
display: none;
}
#sbox-btn-close {
position: absolute;
width: 30px;
height: 30px;
right: -15px;
top: -15px;
background: url(../images/modal/closebox.png) no-repeat center;
border: none;
}
.sbox-loading #sbox-content {
background-image: url(../images/modal/spinner.gif);
background-repeat: no-repeat;
background-position: center;
}
#sbox-content {
clear: both;
overflow: auto;
background-color: #fff;
height: 100%;
width: 100%;
}
.sbox-content-image#sbox-content {
overflow: visible;
}
#sbox-image {
display: block;
}
.sbox-content-image img {
display: block;
width: 100%;
height: 100%;
}
.sbox-content-iframe#sbox-content {
overflow: visible;
}
/* Hides scrollbars */
.body-overlayed {
overflow: hidden;
}
/* Hides flash (Firefox problem) and selects (IE) */
.body-overlayed embed,
.body-overlayed object,
.body-overlayed select {
visibility: hidden;
}
#sbox-window embed,
#sbox-window object,
#sbox-window select {
visibility: visible;
}
/* Shadows */
#sbox-window.shadow {
-webkit-box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
-moz-box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
box-shadow: 0 0 10px rgba(0, 0, 0, 0.7);
}
.sbox-bg {
position: absolute;
width: 33px;
height: 40px;
}
.sbox-bg-n {
left: 0;
top: -40px;
width: 100%;
background: url(../images/modal/bg_n.png) repeat-x;
}
.sbox-bg-ne {
right: -33px;
top: -40px;
background: url(../images/modal/bg_ne.png) no-repeat;
}
.sbox-bg-e {
right: -33px;
top: 0;
height: 100%;
background: url(../images/modal/bg_e.png) repeat-y;
}
.sbox-bg-se {
right: -33px;
bottom: -40px;
background: url(../images/modal/bg_se.png) no-repeat;
}
.sbox-bg-s {
left: 0;
bottom: -40px;
width: 100%;
background: url(../images/modal/bg_s.png) repeat-x;
}
.sbox-bg-sw {
left: -33px;
bottom: -40px;
background: url(../images/modal/bg_sw.png) no-repeat;
}
.sbox-bg-w {
left: -33px;
top: 0;
height: 100%;
background: url(../images/modal/bg_w.png) repeat-y;
}
.sbox-bg-nw {
left: -33px;
top: -40px;
background: url(../images/modal/bg_nw.png) no-repeat;
}
#-moz-document url-prefix() {
.body-overlayed {
overflow: visible;
}
}
#media (max-width: 979px) {
#sbox-window {
overflow: none;
}
#sbox-btn-close {
right: -10px;
top: -10px;
}
}
#media (max-device-width: 979px) {
#sbox-content {
-webkit-overflow-scrolling: touch;
}
#sbox-content.sbox-content-iframe {
overflow: scroll;
-webkit-overflow-scrolling: touch;
}
}
<form action="../massmail.php" method="post">
<label>Periode:</label>
<div class="form-inline">
<input class="form-inline input-small" name="maand" type="text" placeholder="bijv.: juni" />
<input class="input-mini" name="jaar" type="text" value="2015" />
</div>
<br />
<label>Inleidende tekst:</label>
<div>
<textarea name="inleiding" rows="5"></textarea>
</div>
<br />
<label>url van de nieuwsbrief:</label>
<div>
<input class="input-xxlarge" name="link" type="url" value="" />
</div>
<div class="form-actions">
<button class="btn btn-primary" type="submit">Verzenden</button>
<button class="btn" formaction="../voorbeeld.php" formmethod="get" type="submit">Voorbeeld</button>
<a href="index.php">
<button class="btn" type="button">Annuleren</button>
</a>
</div>
</form>

Problem is now solved.
I have used the second line (working popup).
<a class="btn modal" href="voorbeeld.php" rel="{handler: 'iframe', size: {x: 920, y: 530}}">Voorbeeld</a>
As mentioned this does open the popup, but it doesn't seem to process the form, so I deleted the button inside the <a> which was supposed to process the form but didn't send it to the popup.
I have then fetched the form data with Javascript by using:
var id = window.parent.document.getElementById('id').value;
For this to work, all the form elements you want to use in the popup have to have an id.
Hope this helps anyone stumbling upon this.

Related

Nuxt js Custom cursor event listener not working after route change

I'm currently building a new website for our studio but can't get the custom cursor to work properly. Here's a custom cursor built with gsap and the result was great except when I navigate to another route and back to the home page, the mouseover event stops working and I can't find a reason why.
What could be causing this and how could this be fixed?
Thank you in advance!
Here's the CustomCursor component:
<template>
<div class="custom-cursor">
<div id="cursor-big" class="custom-cursor__ball custom-cursor__ball--big"></div>
<div id="cursor-small" class="custom-cursor__ball custom-cursor__ball--small"></div>
</div>
</template>
<script>
import gsap from "gsap";
export default {
props: {
hoverClass: {
type: String,
default: 'cursorHover'
}
},
mounted () {
const cursorBig = document.getElementById('cursor-big'),
cursorSmall = document.getElementById('cursor-small'),
links = document.getElementsByTagName("a"),
withClassHover = document.getElementsByClassName(this.hoverClass),
withHover = [...links, ...withClassHover];
// Event Listeners
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mousedown", onMouseHover);
document.addEventListener("mouseup", onMouseHoverOut);
document.addEventListener("mouseenter", () => {
cursorBig.style.opacity = 1;
cursorSmall.style.opacity = 1;
});
document.addEventListener("mouseleave", () => {
cursorBig.style.opacity = 0;
cursorSmall.style.opacity = 0;
});
withHover.forEach((element) => {
element.addEventListener("mouseover", onMouseHover);
element.addEventListener("mouseout", onMouseHoverOut);
})
// Event Handlers
function onMouseMove(e) {
cursorSmall.style.opacity = 1;
gsap.to(cursorBig, 0.4, {
x: e.clientX - 18.5,
y: e.clientY - 18.5
});
gsap.to(cursorSmall, 0.1, {
x: e.clientX - 4,
y: e.clientY - 4
});
}
function onMouseHover() {
gsap.to(cursorBig, 0.3, {
scale: 3,
});
}
function onMouseHoverOut() {
gsap.to(cursorBig, 0.3, {
scale: 1,
});
}
}
};
</script>
<style>
#media screen and (min-width:1100px) {
* {
cursor: none !important;
}
.custom-cursor__ball {
position: fixed;
top: 0;
left: 0;
mix-blend-mode: difference;
z-index: 99999;
opacity: 0;
pointer-events: none;
transition: opacity 0.5s ease;
}
.custom-cursor__ball--big {
content: "";
width: 35px;
height: 35px;
background: white;
border-radius: 50%;
}
.custom-cursor__ball--small {
content: "";
width: 6px;
height: 6px;
background: #fff;
border-radius: 50%;
}
}
</style>
Moved from comments:
Issue: Elements with cursorHover class are not on the DOM after they have been removed when you route off somewhere else. Mounted only fires once.
Fix: Handle reinitiating your events onto the dom elements, and destroy your custom event handlers as the route changes.
<template>
<div class="custom-cursor">
<div
id="cursor-big"
class="custom-cursor__ball custom-cursor__ball--big"
></div>
<div
id="cursor-small"
class="custom-cursor__ball custom-cursor__ball--small"
></div>
</div>
</template>
<script>
import gsap from "gsap";
export default {
name: "CustomCursor",
props: {
hoverClass: {
type: String,
default: "cursorHover",
},
},
data() {
return {
cursorBig: null,
cursorSmall: null,
withHover: [],
};
},
watch: {
"$route.path"() {
console.log("route change");
this.destroy();
this.$nextTick(this.init);
},
},
mounted() {
console.log("mounted");
this.$nextTick(this.init);
},
beforeDestroy() {
console.log("beforeDestroy");
this.destroy();
},
methods: {
init() {
console.log("init");
setTimeout(() => {
this.cursorBig = document.getElementById("cursor-big");
this.cursorSmall = document.getElementById("cursor-small");
this.withHover = [
...document.getElementsByTagName("a"),
...document.getElementsByClassName(this.hoverClass),
];
this.withHover.forEach((element) => {
element.addEventListener("mouseover", this.onMouseHover);
element.addEventListener("mouseout", this.onMouseHoverOut);
});
document.addEventListener("mousemove", this.onMouseMove);
document.addEventListener("mousedown", this.onMouseHover);
document.addEventListener("mouseup", this.onMouseHoverOut);
document.addEventListener("mouseenter", this.onMouseEnter);
document.addEventListener("mouseleave", this.onMouseLeave);
}, 100);
},
destroy() {
console.log("destroy");
this.withHover.forEach((element) => {
element.removeEventListener("mouseover", this.onMouseHover);
element.removeEventListener("mouseout", this.onMouseHoverOut);
});
document.removeEventListener("mousemove", this.onMouseMove);
document.removeEventListener("mousedown", this.onMouseHover);
document.removeEventListener("mouseup", this.onMouseHoverOut);
document.removeEventListener("mouseenter", this.onMouseEnter);
document.removeEventListener("mouseleave", this.onMouseLeave);
},
onMouseEnter() {
this.cursorBig.style.opacity = 1;
this.cursorSmall.style.opacity = 1;
},
onMouseLeave() {
this.cursorBig.style.opacity = 0;
this.cursorSmall.style.opacity = 0;
},
onMouseMove(e) {
this.cursorSmall.style.opacity = 1;
gsap.to(this.cursorBig, 0.4, {
x: e.clientX - 18.5,
y: e.clientY - 18.5,
});
gsap.to(this.cursorSmall, 0.1, {
x: e.clientX - 4,
y: e.clientY - 4,
});
},
onMouseHover() {
gsap.to(this.cursorBig, 0.3, {
scale: 3,
});
},
onMouseHoverOut() {
gsap.to(this.cursorBig, 0.3, {
scale: 1,
});
},
},
};
</script>
<style>
#media screen and (min-width: 1100px) {
* {
cursor: none !important;
}
.custom-cursor__ball {
position: fixed;
top: 0;
left: 0;
mix-blend-mode: difference;
z-index: 99999;
opacity: 0;
pointer-events: none;
transition: opacity 0.5s ease;
}
.custom-cursor__ball--big {
content: "";
width: 35px;
height: 35px;
background: black;
border-radius: 50%;
}
.custom-cursor__ball--small {
content: "";
width: 6px;
height: 6px;
background: #000;
border-radius: 50%;
}
}
</style>
i currently facing the same issue, but it solved after adding,
this.$next.tick()
so, i just attached the handler when the components is mounted :
mounted() {
this.$nextTick(() => {
this.transitionController()
window.addEventListener('scroll', () => {
this.transitionController()
})
})
},

Pointer Events API and dragging

I'm trying to implement mobile-only touch UI using Pointer Events API and this just isn't working:
https://codepen.io/kyrsquir/full/gOrZEoe
The goal is to allow scrolling in the card and dragging the card between expanded and collapsed state within the same UI. I only managed to get dragging by the handle to work in Chrome emulator and iOS Safari. Dragging via card content doesn't work anywhere.
On Android Chrome dragging doesn't work at all.
The weirdest part is that the same UI works everywhere using touchstart, touchmove and touchend events (https://codepen.io/kyrsquir/full/QWNZzav) but performance of touchmove in Chrome on Android in the presence of scrollbar is so terrible that I'm trying to reimplement it with pointer events.
Vue component code:
<template>
<div class="container">
<div
:class="containerClass"
:style="containerStyle"
#pointerdown="pointerDownHandler"
#pointermove="pointerMoveHandler"
#pointerup="pointerUpHandler"
#pointerover="reportEvent"
#pointerenter="reportEvent"
#pointercancel="reportEvent"
#pointerout="reportEvent"
#pointerleave="reportEvent"
#gotpointercapture="reportEvent"
#lostpointercapture="reportEvent"
#transitionend="transitionEndHandler"
class="card"
>
<svg viewBox="0 0 100 20" always-swipeable="true" class="drag-handle">
<polyline points="27,10 73,10" stroke-linecap="round"></polyline>
</svg>
<div class="scrollbox" ref="scrollbox">
<div :key="item" class="item" v-for="item in items">
{{ item }}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
deltaY: 0,
isDraggingByHandle: false,
isTransitioning: false,
items: [
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
16,
17,
18,
19,
20,
],
offsetHeight: 0,
scrollboxHeight: 0,
scrollTop: 0,
touchAction: null,
verticalStates: [
{
translateY: 0,
},
{
translateY: window.innerHeight - 200,
},
],
verticalStateIndex: 0,
};
},
computed: {
activeVerticalState() {
return this.verticalStates[this.verticalStateIndex];
},
containerClass() {
return {
"show-scrollbar": this.isScrollable,
transition: this.isTransitioning,
};
},
containerStyle() {
return {
transform: `translateY(${this.translateY}px)`,
};
},
isAnySwipeAllowed() {
return this.isDraggingByHandle || !this.isScrollable;
},
isExpanded() {
return this.verticalStateIndex === 0;
},
isScrollable() {
return this.isExpanded && this.scrollHeight > this.offsetHeight;
},
isSwipeDown() {
return (
this.deltaY > 0 && (this.isAnySwipeAllowed || this.scrollTop === 0)
);
},
isSwipeUp() {
return (
this.deltaY < 0 &&
(this.isAnySwipeAllowed ||
this.offsetHeight + this.scrollTop === this.scrollHeight)
);
},
scrollbox() {
return this.$refs.scrollbox;
},
translateY() {
let translateY = this.activeVerticalState.translateY;
if (
this.touchAction === "verticalSwipe" &&
(this.isSwipeDown || this.isSwipeUp)
) {
translateY = translateY + this.deltaY;
}
return translateY;
},
},
mounted() {
this.updateScrollboxData();
},
methods: {
pointerDownHandler: function ({ clientY, target, pointerId }) {
console.log("pointerdown", target, pointerId);
target.setPointerCapture(pointerId);
this.updateScrollboxData();
this.isDraggingByHandle = Boolean(
target.getAttribute("always-swipeable")
);
this.touchStartClientY = clientY;
this.touchAction = "tap";
},
pointerMoveHandler: function ({ clientY, target, pointerId }) {
console.log("pointermove", target, pointerId, this.deltaY);
this.deltaY = clientY - this.touchStartClientY;
// promote touchAction to swipe or scroll depending on deltas and other variables
if (this.touchAction === "tap") {
if (this.isSwipeDown || this.isSwipeUp) {
this.touchAction = "verticalSwipe";
} else {
this.touchAction = "scroll";
this.updateScrollboxData();
}
}
},
pointerUpHandler: function ({ target, pointerId }) {
console.log("pointerup", target, pointerId);
target.releasePointerCapture(pointerId);
switch (this.touchAction) {
case "tap":
if (!this.isExpanded) {
this.verticalStateIndex = Math.max(this.verticalStateIndex - 1, 0);
this.isTransitioning = true;
}
break;
case "verticalSwipe":
if (this.isSwipeDown) {
this.verticalStateIndex = Math.min(
this.verticalStateIndex + 1,
this.verticalStates.length - 1
);
} else if (this.isSwipeUp) {
this.verticalStateIndex = Math.max(this.verticalStateIndex - 1, 0);
}
this.isTransitioning = true;
this.deltaY = 0;
break;
}
},
reportEvent({ type, target, pointerId }) {
console.log(type, target, pointerId);
},
transitionEndHandler() {
this.touchAction = null;
this.isTransitioning = false;
this.updateScrollboxData();
},
updateScrollboxData() {
const { scrollHeight, offsetHeight, scrollTop } = this.scrollbox;
this.offsetHeight = offsetHeight;
this.scrollHeight = scrollHeight;
this.scrollTop = scrollTop;
},
},
};
</script>
<style lang="scss" scoped>
.container {
display: flex;
justify-content: center;
margin-top: 5vh;
overflow: hidden;
touch-action: none;
.card {
pointer-events: all;
width: 90vw;
height: 100%;
touch-action: none;
&.transition {
transition: transform 0.15s ease-out;
}
.drag-handle {
stroke-width: 5px;
stroke: #bfbfc0;
width: 100%;
height: 30px;
background: pink;
}
.scrollbox {
overflow-y: hidden;
pointer-events: none;
background: green;
height: 85vh;
.item {
margin-bottom: 20px;
height: 150px;
font-size: 36px;
background: yellow;
}
}
&.show-scrollbar .scrollbox {
overflow-y: scroll;
pointer-events: all;
}
}
}
</style>

Mix-Blend mode doesn't work on custom cursor

I would like to add a mix-blend-mode: difference to the inner cursor, but I can't get it to work. I heard that the position: fixed applied to the cursor may cause the problem here. But I can't remove that property, because the cursor needs to follow when scrolling down. Does anyone know how to fix the problem here? Thank you in advance.
class Demo {
constructor() {
this.initCursor();
this.initHovers();
}
initCursor() {
const { Back } = window;
this.outerCursor = document.querySelector(".circle-cursor-outer");
this.innerCursor = document.querySelector(".circle-cursor-inner");
this.outerCursorBox = this.outerCursor.getBoundingClientRect();
this.outerCursorSpeed = 0;
this.easing = Back.easeOut.config(1.7);
this.clientX = -100;
this.clientY = -100;
this.showCursor = false;
const unveilCursor = () => {
TweenMax.set(this.innerCursor, {
x: this.clientX,
y: this.clientY
});
TweenMax.set(this.outerCursor, {
x: this.clientX - this.outerCursorBox.width / 2,
y: this.clientY - this.outerCursorBox.height / 2
});
setTimeout(() => {
this.outerCursorSpeed = 0.2;
}, 100);
this.showCursor = true;
};
document.addEventListener("mousemove", unveilCursor);
document.addEventListener("mousemove", e => {
this.clientX = e.clientX;
this.clientY = e.clientY;
});
const render = () => {
TweenMax.set(this.innerCursor, {
rotation: 90,
x: this.clientX,
y: this.clientY
});
if (!this.isStuck) {
TweenMax.to(this.outerCursor, this.outerCursorSpeed, {
x: this.clientX - this.outerCursorBox.width / 2,
y: this.clientY - this.outerCursorBox.height / 2
});
}
if (this.showCursor) {
document.removeEventListener("mousemove", unveilCursor);
}
requestAnimationFrame(render);
};
requestAnimationFrame(render);
}
initHovers() {
const handleMouseEnter = e => {
this.isStuck = true;
const target = e.currentTarget;
const box = target.getBoundingClientRect();
this.outerCursorOriginals = {
width: this.outerCursorBox.width,
height: this.outerCursorBox.height
};
TweenMax.to(this.innerCursor, 0.2, {
x: box.left,
y: box.top,
width: box.width,
height: box.height,
opacity: 0.4,
});
};
const handleMouseLeave = () => {
this.isStuck = false;
TweenMax.to(this.innerCursor, 0.2, {
width: this.outerCursorOriginals.width,
height: this.outerCursorOriginals.height,
opacity: 0.2,
});
};
const mainNavHoverTween = TweenMax.to(this.innerCursor, 0.3, {
ease: this.easing,
paused: true,
opacity: 1,
width: 70,
height: 70,
left: -35,
top: -35
});
const mainNavMouseEnter = () => {
this.outerCursorSpeed = 0;
TweenMax.set(this.innerCursor, { opacity: 1 });
mainNavHoverTween.play();
};
const mainNavMouseLeave = () => {
this.outerCursorSpeed = 0.2;
TweenMax.set(this.innerCursor, { opacity: 1 });
mainNavHoverTween.reverse();
};
const mainNavLinks = document.querySelectorAll("a");
mainNavLinks.forEach(item => {
item.addEventListener("mouseenter", mainNavMouseEnter);
item.addEventListener("mouseleave", mainNavMouseLeave);
});
}
}
const demo = new Demo();
body{
height: 500vh;
}
a{
color: black;
}
.circle-cursor {
position: fixed;
left: 0;
top: 0;
pointer-events: none;
border-radius: 100%;
}
.circle-cursor-outer-badge {
opacity: 0.5;
transition: all 500ms ease-out;
}
.circle-cursor-inner {
width: 22.5px;
height: 22.5px;
left: -11.25px;
top: -11.25px;
z-index: 11000;
mix-blend-mode: difference;
background-color: black;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
I am a link
<div class="circle-cursor circle-cursor-outer">
<img class="circle-cursor-outer-badge" draggable="false" width="120" src="https://svgshare.com/i/H2V.svg">
</div>
<div class="circle-cursor circle-cursor-inner"></div>
</body>
Just set background:white to both body and .circle-cursor-inner:
class Demo {
constructor() {
this.initCursor();
this.initHovers();
}
initCursor() {
const { Back } = window;
this.outerCursor = document.querySelector(".circle-cursor-outer");
this.innerCursor = document.querySelector(".circle-cursor-inner");
this.outerCursorBox = this.outerCursor.getBoundingClientRect();
this.outerCursorSpeed = 0;
this.easing = Back.easeOut.config(1.7);
this.clientX = -100;
this.clientY = -100;
this.showCursor = false;
const unveilCursor = () => {
TweenMax.set(this.innerCursor, {
x: this.clientX,
y: this.clientY
});
TweenMax.set(this.outerCursor, {
x: this.clientX - this.outerCursorBox.width / 2,
y: this.clientY - this.outerCursorBox.height / 2
});
setTimeout(() => {
this.outerCursorSpeed = 0.2;
}, 100);
this.showCursor = true;
};
document.addEventListener("mousemove", unveilCursor);
document.addEventListener("mousemove", e => {
this.clientX = e.clientX;
this.clientY = e.clientY;
});
const render = () => {
TweenMax.set(this.innerCursor, {
rotation: 90,
x: this.clientX,
y: this.clientY
});
if (!this.isStuck) {
TweenMax.to(this.outerCursor, this.outerCursorSpeed, {
x: this.clientX - this.outerCursorBox.width / 2,
y: this.clientY - this.outerCursorBox.height / 2
});
}
if (this.showCursor) {
document.removeEventListener("mousemove", unveilCursor);
}
requestAnimationFrame(render);
};
requestAnimationFrame(render);
}
initHovers() {
const handleMouseEnter = e => {
this.isStuck = true;
const target = e.currentTarget;
const box = target.getBoundingClientRect();
this.outerCursorOriginals = {
width: this.outerCursorBox.width,
height: this.outerCursorBox.height
};
TweenMax.to(this.innerCursor, 0.2, {
x: box.left,
y: box.top,
width: box.width,
height: box.height,
opacity: 0.4,
});
};
const handleMouseLeave = () => {
this.isStuck = false;
TweenMax.to(this.innerCursor, 0.2, {
width: this.outerCursorOriginals.width,
height: this.outerCursorOriginals.height,
opacity: 0.2,
});
};
const mainNavHoverTween = TweenMax.to(this.innerCursor, 0.3, {
ease: this.easing,
paused: true,
opacity: 1,
width: 70,
height: 70,
left: -35,
top: -35
});
const mainNavMouseEnter = () => {
this.outerCursorSpeed = 0;
TweenMax.set(this.innerCursor, { opacity: 1 });
mainNavHoverTween.play();
};
const mainNavMouseLeave = () => {
this.outerCursorSpeed = 0.2;
TweenMax.set(this.innerCursor, { opacity: 1 });
mainNavHoverTween.reverse();
};
const mainNavLinks = document.querySelectorAll("a");
mainNavLinks.forEach(item => {
item.addEventListener("mouseenter", mainNavMouseEnter);
item.addEventListener("mouseleave", mainNavMouseLeave);
});
}
}
const demo = new Demo();
body{
height: 500vh;
background:white;
}
a{
color: black;
}
.circle-cursor {
position: fixed;
left: 0;
top: 0;
pointer-events: none;
border-radius: 100%;
}
.circle-cursor-outer-badge {
opacity: 0.5;
transition: all 500ms ease-out;
}
.circle-cursor-inner {
width: 22.5px;
height: 22.5px;
left: -11.25px;
top: -11.25px;
z-index: 11000;
mix-blend-mode: difference;
background: white;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/1.18.0/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body>
I am a link
<div class="circle-cursor circle-cursor-outer">
<img class="circle-cursor-outer-badge" draggable="false" width="120" src="https://svgshare.com/i/H2V.svg">
</div>
<div class="circle-cursor circle-cursor-inner"></div>
</body>

Fabric 3.4.0 Text formatting

I have been working on Fabric 3.4.0 and want to know how do I format the text, something show here IText tests
I have been using 1.5.0 version and it works fine but it doesn't work on the latest version can someone help me fix the issue with the cdn on 3.4.0
var canvas=new fabric.Canvas('canv');
var iTextSample = new fabric.IText('hello\nworld', {
left: 50,
top: 50,
fontFamily: 'Helvetica',
fill: '#333',
lineHeight: 1.1,
styles: {
0: {
0: { textDecoration: 'underline', fontSize: 80 },
1: { textBackgroundColor: 'red' }
},
1: {
0: { textBackgroundColor: 'rgba(0,255,0,0.5)' },
4: { fontSize: 20 }
}
}
});
canvas.add(iTextSample);
function addHandler(id, fn, eventName) {
document.getElementById(id)[eventName || 'onclick'] = function() {
var el = this;
if (obj = canvas.getActiveObject()) {
fn.call(el, obj);
canvas.renderAll();
}
};
}
function setStyle(object, styleName, value) {
if (object.setSelectionStyles && object.isEditing) {
var style = { };
style[styleName] = value;
object.setSelectionStyles(style);
}
else {
object[styleName] = value;
}
}
function getStyle(object, styleName) {
return (object.getSelectionStyles && object.isEditing)
? object.getSelectionStyles()[styleName]
: object[styleName];
}
addHandler('underline', function(obj) {
var isUnderline = (getStyle(obj, 'textDecoration') || '').indexOf('underline') > -1;
setStyle(obj, 'textDecoration', isUnderline ? '' : 'underline');
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/1.5.0/fabric.min.js"></script>
<button id="underline">Underline it!!</button>
<canvas id="canv" width="250" height="300" style="border: 1px solid rgb(204, 204, 204); width: 400px; height: 400px; -webkit-user-select: none;"></canvas>
After v2, textDecoration property is removed, and separated to underline, overline, linethrough to support multiple text decoration.
DEMO
var canvas=new fabric.Canvas('canv');
var value = false;
var iTextSample = new fabric.IText('hello\nworld', {
left: 50,
top: 50,
fontFamily: 'Helvetica',
fill: '#333',
lineHeight: 1.1,
styles: {
0: {
0: { underline: true, fontSize: 80 },
1: { textBackgroundColor: 'red' }
},
1: {
0: { textBackgroundColor: 'rgba(0,255,0,0.5)' },
4: { fontSize: 20 }
}
}
});
canvas.add(iTextSample);
function addHandler(id, fn, eventName) {
document.getElementById(id)[eventName || 'onclick'] = function() {
var el = this;
if (obj = canvas.getActiveObject()) {
fn.call(el, obj);
canvas.renderAll();
}
};
}
function getStyle(object, styleName) {
return (object.getSelectionStyles && object.isEditing)
? object.getSelectionStyles()
: object[styleName];
}
addHandler('underline', function(obj) {
var selectionStyle = obj.getSelectionStyles();
value = !value;
if(selectionStyle.length)
obj.setSelectionStyles({underline: value});
else
obj.setSelectionStyles({underline: value}, 0, obj.text.length);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.4.0/fabric.js"></script>
<button id="underline">Underline it!!</button>
<canvas id="canv" width="250" height="300" style="border: 1px solid rgb(204, 204, 204); width: 400px; height: 400px; -webkit-user-select: none;"></canvas>

How to generate Canvas layer with on click button

i have a question - how to draw canvas layer (for example just simple square) with event on click on button in Vue.js? I have stage and on that stage with position x:0, y:0 i want after click on button to generate that square and with drag and drop to position it on that stage? I'm using Konvajs for creating Canvas
Can somebody help me?
<template>
<div id="main">
<h1></h1>
<div id="obszarroboczy" style="width: 500px; height: 600px;">
<v-stage ref="stage"
:config="configKonva"
#dragstart="handleDragstart"
#dragend="handleDragend">
<v-layer ref="layer">
<v-star
v-for="item in list"
:key="item.id"
:config="item"></v-star>
</v-layer>
<v-layer ref="dragLayer"></v-layer>
</v-stage>
</div>
<div class="col-md-6">
<button v-on:click="handleClick" id="more_canvas">More</button>
</div>
</div>
</template>
<script>
import Vue from "vue";
import axios from "axios";
import draggable from "vuedraggable";
import swal from "sweetalert2";
import VueKonva from "vue-konva";
export default {
name: "EnumCurrencyIndex",
$mount: "#main",
components: {
draggable
},
data() {
return {
model: [],
editable: true,
isDragging: false,
delayedDragging: false,
type: "currency",
editedElement: null,
newElement: "",
list: [],
configKonva: {
width: 400,
height: 400
},
configCircle: {
x: 100,
y: 100,
radius: 70,
fill: 'red',
stroke: 'black',
strokeWidth: 4
},
vm: {}
};
},
beforeMount() {
this.fetchData();
},
computed: {
dragOptions() {
return {
animation: 0,
group: "description",
disabled: !this.editable,
ghostClass: "ghost"
};
},
listString() {
return this.model;
},
dragCanvas() {
return this.model;
}
},
watch: {
$route: "fetchData",
isDragging(newValue) {
if (newValue) {
this.delayedDragging = true;
return;
}
this.$nextTick(() => {
this.delayedDragging = false;
});
}
},
methods: {
handleDragstart(starComponent) {
var vm = this;
const shape = starComponent.getStage();
const dragLayer = vm.$refs.dragLayer.getStage();
const stage = vm.$refs.stage.getStage();
// moving to another layer will improve dragging performance
shape.moveTo(dragLayer);
stage.draw();
starComponent.config.shadowOffsetX = 15;
starComponent.config.shadowOffsetY = 15;
starComponent.config.scaleX = starComponent.config.startScale * 1.2;
starComponent.config.scaleY = starComponent.config.startScale * 1.2;
},
handleDragend(starComponent) {
var vm = this;
const shape = starComponent.getStage();
const layer = vm.$refs.layer.getStage();
const stage = vm.$refs.stage.getStage();
shape.moveTo(layer);
stage.draw();
shape.to({
duration: 0.5,
easing: Konva.Easings.ElasticEaseOut,
scaleX: starComponent.config.startScale,
scaleY: starComponent.config.startScale,
shadowOffsetX: 5,
shadowOffsetY: 5
});
},
handleClick(configCircle) {
var vm = this;
const shape = vm.$refs.layer.getStage();
const layer = vm.$refs.layer.getStage();
const stage = vm.$refs.stage.getStage();
console.log(1);
layer.add(configCircle);
stage.add(layer);
},
haveIntersection(r1, r2) {
return !(
r2.x > r1.x + r1.width ||
r2.x + r2.width < r1.x ||
r2.y > r1.y + r1.height ||
r2.y + r2.height < r1.y
);
},
orderList() {
this.model = this.model.sort((one, two) => {
return one.position - two.position;
});
},
onMove({ relatedContext, draggedContext }) {
const relatedElement = relatedContext.element;
const draggedElement = draggedContext.element;
return (
(!relatedElement || !relatedElement.fixed) && !draggedElement.fixed
);
},
fetchData() {
var vm = this;
axios
.get(`/api/${this.resource}?type=${this.type}`)
.then(function(response) {
Vue.set(vm.$data, "model", response.data.model);
})
.catch(function(error) {
console.log(error);
});
}
},
mounted() {
var box = document.getElementById("obszarroboczy");
this.configKonva.width = box.offsetWidth;
this.configKonva.height = box.offsetHeight;
var vm = this;
for (let n = 0; n < 30; n++) {
const scale = Math.random();
const stage = vm.$refs.stage.getStage();
vm.list.push({
x: Math.random() * stage.getWidth(),
y: Math.random() * stage.getHeight(),
rotation: Math.random() * 180,
numPoints: 5,
innerRadius: 30,
outerRadius: 50,
fill: "#89b717",
opacity: 0.8,
draggable: true,
scaleX: scale,
scaleY: scale,
shadowColor: "black",
shadowBlur: 10,
shadowOffsetX: 5,
shadowOffsetY: 5,
shadowOpacity: 0.6,
startScale: scale
});
};
},
directives: {
"element-focus": function(el, binding) {
if (binding.value) {
el.focus();
}
}
}
};
</script>
<style>
#obszarroboczy {
width: 100px;
height: 300px;
}
.normal {
background-color: grey;
}
.table td {
width: 100px;
height: 100px;
background: white;
border: 2px dotted black;
max-width: 100px;
padding: 5px;
}
.drag {
display: flex;
flex-direction: row;
}
.list {
flex-grow: 1;
max-width: 47%;
margin-right: 40px;
}
.name {
width: 50%;
display: inline-block;
height: 50px;
background: pink;
border: 5px green solid;
box-sizing: border-box;
padding: 5px;
}
.name.large {
width: 100%;
}
.dragArea {
min-height: 100px;
}
.dragArea img {
margin: 3px;
cursor: pointer;
}
</style>
var mainCanvas = new Vue({
el: '#main', // the element where the method wil lrender the canvas to
data: {
name: 'Vue.js'
},
methods: {
handleClick: function (event) { // handleClick is the method name for the button
var stage = new Konva.Stage({ // this line till the stage.add() line renders the draggable square
container: 'obszarroboczy',
width: 500,
height: 500
});
var layer = new Konva.Layer();
var rect = new Konva.Rect({
x: 0,
y: 0,
width: 100,
height: 100,
fill: 'green',
stroke: 'black',
strokeWidth: 4,
draggable: true
});
layer.add(rect);
stage.add(layer);
}
}
});
I added comments to explain what certain important lines does but you can check out the official KonvaJS Docs in GitHub for a more detailed explanation on what each line above does.

Categories

Resources