vue-konva - Add filters to image - vue.js

I am using vue-konva with vuejs and I can't appy konva filters on my elements.
I have implemented my component like this :
<template>
<div>
<v-stage ref="stage" :config="configKonva">
<v-layer ref="layer">
<v-image ref="maskelement" :config="imageConfig" />
<v-circle :config="configCircle"></v-circle>
</v-layer>
</v-stage>
</div>
</template>
<script>
export default {
name: 'mySvg',
data() {
const img = new Image();
img.src = 'myImagePath.png';
return {
configCircle: {
x: 500,
y: 200,
radius: 70,
fill: 'red',
stroke: 'pink',
strokeWidth: 4,
},
imageConfig: {
x: 0,
y: 0,
image: img,
width: 1181,
height: 1181,
filters: [
Konva.Filters.Mask,
],
threshold: 200,
},
};
},
};
</script>
I have also tryed to add a sceneFunc attribute to imageConfig like this :
imageConfig: {
x: 0,
y: 0,
image: img,
width: 1181,
height: 1181,
sceneFunc: (context, elem) => {
elem.filters([Konva.Filters.Mask]);
elem.threshold(200);
},
},
But as soon as there is a sceneFunc attribute, my component won't display
How should I use filters with vuejs?

You can use this code to apply cache to the image:
<template>
<v-stage :config="{
width: 300,
height: 300
}">
<v-layer>
<v-image :config="{
image: this.image,
filters: this.filters,
blur: 100,
scaleX: 0.3,
scaleY: 0.3
}" ref="image"></v-image>
</v-layer>
</v-stage>
</template>
<script>
import VueKonva from 'vue-konva'
import Vue from 'vue';
Vue.use(VueKonva)
export default {
name: "App",
data() {
return {
image: null,
filters: [Konva.Filters.Blur]
}
},
created() {
var img = new Image();
img.src = './logo.png';
img.onload = () => {
this.image = img;
this.$nextTick(() => {
const node = this.$refs.image.getStage();
node.cache();
node.getLayer().batchDraw();
})
}
}
};
</script>

Related

How to dynamically update data in chart.js

How to update the data to the chart that I define when I mount?
I think that I fail to properly reference the chart?
It is the data() function that fails, with "Could not find linechart", but how do I specify linechart?
I have made
this code sandbox
<template>
<div class="container center">
<div class="px-3">
<label for="Product">Select a:</label>
<select
class="border-solid border-2 rounded-md p-1 font-bold"
v-on:input="outputData()"
id="Product"
aria-placeholder="Product"
>
<option value="" disabled selected>Product</option>
<option>1</option>
</select>
</div>
<div>
<canvas id="line-chart"></canvas>
</div>
</div>
</template>
<script>
import Chart from "chart.js/auto";
export default {
name: "line-plot",
mounted() {
const ctx = document.getElementById("line-chart");
const linechart = new Chart(ctx, this.chartData);
return linechart;
},
data() {
return {
chartData: {
type: "line",
data: {
labels: ["a", "b", "c"],
datasets: [
{
label: "Contract",
data: [5, 5, 5],
borderColor: "#9B202A",
borderWidth: 3,
},
{
label: "FWD",
data: [5, 10, 15],
borderColor: "#6F6F6F",
borderWidth: 3,
},
],
},
},
options: [],
};
},
methods: {
outputData() {
const contractPrice = {
label: "Contract",
data: [6, 6, 6],
borderColor: "#9B202A",
borderWidth: 3,
};
const fwdPrice = {
label: "FWD",
data: [10, 10, 10],
borderColor: "#6F6F6F",
borderWidth: 3,
};
const labels = ["a", "b", "c"];
this.chartData.data.labels = labels;
this.chartData.data.datasets[0] = contractPrice;
this.chartData.data.datasets[1] = fwdPrice;
linechart.update();
},
},
};
</script>
<style>
.center {
margin: auto;
}
</style>
You should define your variable to hold the Chart outside the mounted function in order to be visible to the other methods.
So instead use this
let linechart;
export default {
name: "line-plot",
mounted() {
const ctx = document.getElementById("line-chart");
linechart = new Chart(ctx, this.chartData);
},
sandbox

google maps addListener not working properly with vue3-google-map

I want to use addListener("bounds_changed") to display the sides of the box when changing to the user in vuejs
How can I display the dimensions of the drawing on the map after adjusting its area
<script>
import { defineComponent } from 'vue';
import { GoogleMap,Rectangle ,InfoWindow } from "vue3-google-map";
export default defineComponent({
components: { GoogleMap, Rectangle ,InfoWindow },
setup() {
const center = { lat: 33.678, lng: -116.243 };
const bounds= "<h2>dasd</h2>";
const rectangle = {
strokeColor: "#FF0000",
strokeOpacity: 0.8,
strokeWeight: 2,
fillColor: "#FF0000",
fillOpacity: 0.35,
editable: true,
draggable: true,
bounds: {
north: 33.685,
south: 33.671,
east: -116.234,
west: -116.251,
},
};
// bound=rectangle.addListener("bounds_changed", bounds);
return { center, rectangle ,bounds};
},
});
</script>
<template>
<GoogleMap
api-key="API_KEY"
style="width: 100%; height: 500px"
mapTypeId="terrain"
:center="center"
:zoom="11"
>
<Rectangle :options="rectangle" />
</GoogleMap>
<div class="show"></div>
</template>

How to display markerClusters by axios props with Vue 3 and vue-Leaflet?

I have a problem to display the markerClusters after receive by props in my component Map :
<template>
<div>
<LMap
v-show="showLoading"
class="map"
ref="map"
:center="center"
:zoom="zoom"
:maxZoom="max"
:minZoom="min"
:options="{ attributionControl: false }"
#ready="onLeafletReady"
:zoomAnimation="true"
:markerZoomAnimation="true"
:useGlobalLeaflet="true"
>
<template v-if="leafletReady">
<LTileLayer
v-for="tileProvider in tileProviders"
:attribution="tileProvider.attribution"
:key="tileProvider.name"
layer-type="base"
:name="tileProvider.name"
:url="tileProvider.url"
:visible="tileProvider.visible"
>
</LTileLayer>
<LControlScale position="bottomleft" :imperial="false" :metric="true" />
<LControlAttribution position="bottomright" prefix="FTM" />
<LControlLayers />
<div class="loader" v-if="loading" />
</template>
</LMap>
</div>
</template>
<script>
import { defineComponent, ref } from "vue"
import * as L from "leaflet"
import "leaflet.markercluster/dist/leaflet.markercluster.js"
import "leaflet/dist/leaflet.css"
import "leaflet.markercluster/dist/MarkerCluster.css"
import "leaflet.markercluster/dist/MarkerCluster.Default.css"
import {
LControlAttribution,
LControlLayers,
LControlScale,
LMap,
LTileLayer
} from "#vue-leaflet/vue-leaflet"
export default defineComponent({
components: {
LControlAttribution,
LControlLayers,
LControlScale,
LMap,
LTileLayer
},
props: {
pois: {
type: Array,
default: null
}
},
setup() {
return {
showLoading: ref(true),
zoom: ref(7),
center: ref({ lat: 48.85664, lng: 2.35347 })
}
},
data() {
return {
leafletReady: false,
poiMarkersGroup: null,
attribution:
'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors',
max: 19,
min: 6,
tileProviders: [
{
name: this.$t("map.mapTiles.standard"),
visible: true,
maxZoom: 19,
attribution:
'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors',
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
},
{
name: this.$t("map.mapTiles.satellite"),
visible: false,
maxZoom: 17,
url: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
attribution:
"Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
},
{
name: this.$t("map.mapTiles.urbanTransport"),
visible: false,
maxZoom: 20,
attribution:
'© OpenStreetMap France | © OpenStreetMap contributors',
url: "https://{s}.tile.openstreetmap.fr/osmfr/{z}/{x}/{y}.png"
},
{
name: this.$t("map.mapTiles.cyclePaths"),
visible: false,
maxZoom: 20,
attribution:
'CyclOSM | Map data: © OpenStreetMap contributors',
url: "https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png"
}
],
url: "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
}
},
methods: {
async onLeafletReady(_map) {
await this.$nextTick()
this.leafletReady = true
},
compilClusters(pois, nbPois) {
L.Map.addInitHook(function () {
const markerCluster = L.markerClusterGroup({
removeOutsideVisibleBounds: true,
chunkedLoading: true,
showCoverageOnHover: false
}).addTo(this)
let markers = []
for (let i = 0; i < nbPois; i++) {
const marker = L.marker(L.latLng(pois[i].coords))
marker.bindPopup(
"<ul style='padding: 0; list-style-type: none;'>" +
"<li style='font-weight: bold;'>" +
pois[i].name +
"<li>" +
pois[i].address +
"</li>" +
"</li>" +
"<li>" +
pois[i].postalCode +
" " +
pois[i].city +
"</li>" +
"</ul>"
)
markers.push(marker)
markerCluster.addLayers(markers)
}
})
}
},
watch: {
pois(val) {
if (val !== null) {
this.compilClusters(val, val.length)
}
}
}
})
</script>
<style lang="scss" scoped>
.map {
width: 100%;
height: 100%;
height: 100vh;
}
</style>
I'm using Quasar+leaflet+#vue-leaflet/vue-leaflet and leaflet.markercluster.
I guess based on code https://codesandbox.io/s/vue-3-leaflet-marker-cluster-poc-forked-ns238?file=/components/TestMap.vue:2715-3306
When I send the latlng by props, the coordinates are passed to the compilClusters(latLng, nbOfLatLng) function through the watch() function.
But they are not displayed, if I reload my page, they are displayed!
How to display it when I receive them by props?

How to connect 2 objects using a line using konvajs in vuejs?

Good morning, I find myself working with the Konvajs library, https://github.com/konvajs/vue-konva
There is the following documentation: https://konvajs.org/docs/sandbox/Connected_Objects.html, but I can't implement it with vuejs
Since what I need to do is that when selecting object 1, I can drag and form the arrow and when selecting object 2, they are linked
Currently I have built the following:
<template>
<v-container>
<v-stage :config="configKonva">
<v-layer>
<v-circle :config="configCircle"></v-circle>
</v-layer>
<v-layer>
<v-circle :config="configCircleA"></v-circle>
</v-layer>
</v-stage>
</v-container>
</template>
<script>
export default {
data(){
return {
configKonva: {
width: 200,
height: 200
},
configCircle: {
x: 100,
y: 100,
radius: 70,
fill: "red",
stroke: "black",
strokeWidth: 4,
draggable: true
},
configCircleA: {
x: 100,
y: 100,
radius: 70,
fill: "green",
stroke: "black",
strokeWidth: 4,
draggable: true
}
}
},
}
</script>
Visually I have only created the circles, I lack the connection of these 2 through a line
There are many ways to implement such functionality. Basically, you just need to listen to mousedown, mousemove and mouseup events to understand when to draw lines. You can also add touchstart, touchmove and touchend events to support mobile devices:
<template>
<div>
<v-stage
ref="stage"
:config="stageSize"
#mousedown="handleMouseDown"
#mouseup="handleMouseUp"
#mousemove="handleMouseMove"
>
<v-layer>
<v-line
v-for="line in connections"
:key="line.id"
:config="{
stroke: 'black',
points: line.points
}"
/>
<v-circle
v-for="target in targets"
:key="target.id"
:config="{
x: target.x,
y: target.y,
radius: 40,
stroke: 'black',
fill: 'green'
}"
/>
<v-text :config="{ text: 'Try to drag-to-connect objects'}"/>
</v-layer>
<v-layer ref="dragLayer"></v-layer>
</v-stage>
</div>
</template>
<script>
import Konva from "konva";
const width = window.innerWidth;
const height = window.innerHeight;
let vm = {};
function generateTargets() {
const circles = [];
for (var i = 0; i < 10; i++) {
circles.push({
x: width * Math.random(),
y: height * Math.random(),
id: i
});
}
return circles;
}
export default {
data() {
return {
stageSize: {
width: width,
height: height
},
targets: generateTargets(),
connections: [],
drawningLine: false
};
},
methods: {
handleMouseDown(e) {
const onCircle = e.target instanceof Konva.Circle;
if (!onCircle) {
return;
}
this.drawningLine = true;
this.connections.push({
id: Date.now(),
points: [e.target.x(), e.target.y()]
});
},
handleMouseMove(e) {
if (!this.drawningLine) {
return;
}
const pos = e.target.getStage().getPointerPosition();
const lastLine = this.connections[this.connections.length - 1];
lastLine.points = [lastLine.points[0], lastLine.points[1], pos.x, pos.y];
},
handleMouseUp(e) {
const onCircle = e.target instanceof Konva.Circle;
if (!onCircle) {
return;
}
this.drawningLine = false;
const lastLine = this.connections[this.connections.length - 1];
lastLine.points = [
lastLine.points[0],
lastLine.points[1],
e.target.x(),
e.target.y()
];
}
}
};
</script>
DEmo: https://codesandbox.io/s/vue-konva-connection-objects-qk2ps

Slideshow is properly showed only first time, then it dissapears

I have a problem properly displaying slideshow (which is written in Jquery) when i revisit web page (via router-link)...
So if i press f5 and web page reloads, everything is working properly, but once i click on one link and i'm redirected, half of web page is blank... I belive that problem is because a lot of parts of this application is in jquery code. I bought a template and include it in to my Vuejs2 project
Example of home component
<template>
<div id="wrapper">
<HeaderComponent></HeaderComponent>
<div id="main-content">
<SlideShow></SlideShow>
</div>
<FooterComponent></FooterComponent>
</div>
</template>
<script>
import HeaderComponent from './HeaderComponent.vue'
import SlideShow from './subComponents/SlideShow.vue'
import FooterComponent from './FooterComponent.vue'
export default {
name: 'Home',
components: {
'HeaderComponent': HeaderComponent,
'SlideShow': SlideShow,
'FooterComponent': FooterComponent
}
}
</script>
Slideshow component
<template>
<div class="">
<div class="rev_slider_wrapper">
<div id="rev_slider" data-slider-layout="fullscreen" data-slider-thumbnail="true" class="rev_slider">
<ul>
<li><img src="static/img/various/bg-image.png"/></li>
</ul>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'SlideShow'
}
</script>
This is the slider.js included in index.html via tag
$(document).ready(function () {
// MAIN VARIABLES INITIALIZATION
var revapi;
$(window).resize(function () {
'use strict';
if ($('#rev_slider').data('slider-layout') == 'fullscreen' && $('body').hasClass('left-nav')) {
var windowHeight = $(window).height();
$('.rev_slider_wrapper, #rev_slider').height(windowHeight);
}
});
(function () {
'use strict';
slickCarousel();
setTimeout(function () {
revSlider();
owlCarousel();
}, 100);
bxSlider();
flexslider();
}());
// REVOLUTION SLIDER
function revSlider() {
if ($.fn.revolution && $('#rev_slider').length) {
var revSliderLayout = $('#rev_slider').data('slider-layout') ? $('#rev_slider').data('slider-layout') : 'auto';
var revSliderHeight = $('#rev_slider').data('gridheight') ? $('#rev_slider').data('gridheight') : [800, 800, 480, 360];
var windowHeight = $(window).height();
if ($('body').hasClass('left-nav')) {
revSliderLayout = 'auto';
if ($('#rev_slider').data('slider-layout') == 'fullscreen') {
revSliderHeight = windowHeight;
}
}
revapi = $('#rev_slider').show().revolution({
sliderType: $('#rev_slider').data('slider-type') ? $('#rev_slider').data('slider-type') : 'standard',// standard, hero, carousel
jsFileLocation: 'static/js/plugins/revolution-slider/revolution/js/',
sliderLayout: revSliderLayout, // auto, fullscreen, fullwidth
dottedOverlay: 'none',
delay: 9000,
lazyLoad: 'on',
navigation: {
keyboardNavigation: 'on',
keyboard_direction: 'horizontal',
mouseScrollNavigation: $('#rev_slider').data('nav-mouse') ? $('#rev_slider').data('nav-mouse') : 'off',
onHoverStop: 'off',
touch: {
touchenabled: 'on',
swipe_threshold: 75,
swipe_min_touches: 1,
swipe_direction: 'horizontal',
drag_block_vertical: false
},
arrows: {
style: 'zeus',
enable: $('#rev_slider').attr('data-nav-arrows') ? false : true,
hide_onmobile: false,
hide_onleave: false,
tmp: $('#rev_slider').data('slider-thumbnail') ? '<div class="tp-title-wrap"><div class="tp-arr-imgholder"></div></div>' : '<div class="tp-title-wrap"></div>',
left: {
h_align: 'left',
v_align: 'center',
h_offset: 10,
v_offset: 0
},
right: {
h_align: 'right',
v_align: 'center',
h_offset: 10,
v_offset: 0
}
},
bullets: {
enable: $('#rev_slider').attr('data-nav-bullets') ? true : false,
hide_onmobile: false,
style: 'uranus',
hide_onleave: false,
direction: 'vertical',
h_align: $('#rev_slider').data('bullets-align') ? $('#rev_slider').data('bullets-align') : 'left',
v_align: 'center',
h_offset: 30,
v_offset: 0,
space: 10,
tmp: '<span class="tp-bullet-inner"></span>'
}
},
carousel: {
maxRotation: 5,
vary_rotation: "off",
minScale: 15,
vary_scale: "off",
horizontal_align: "center",
vertical_align: "center",
fadeout: "on",
vary_fade: "on",
maxVisibleItems: 3,
infinity: "off",
space: -80,
stretch: "off"
},
responsiveLevels: $(this).data('responsive') ? $(this).data('responsive') : [1240, 1024, 778, 480],
gridwidth: $(this).data('gridwidth') ? $(this).data('gridwidth') : [1230, 1024, 767, 480],
gridheight: revSliderHeight,
lazyType: 'none',
parallax: {
type: 'mouse',
origo: 'slidertop',
speed: 2000,
levels: [2, 3, 4, 5, 6, 7, 12, 16, 10, 50],
disable_onmobile: 'on'
},
shadow: 0,
spinner: 'off',
stopLoop: 'on',
stopAfterLoops: 0,
// stopAtSlide: $('#rev_slider').data('autoplay') ? 0 : 1,
shuffle: 'off',
autoHeight: 'off',
disableProgressBar: 'on',
hideThumbsOnMobile: 'off',
hideSliderAtLimit: 0,
hideCaptionAtLimit: 0,
hideAllCaptionAtLilmit: 0,
startWithSlide: 0,
fallbacks: {
simplifyAll: 'off',
nextSlideOnWindowFocus: 'off',
disableFocusListener: 'off'
}
});
revapi.bind("revolution.slide.onbeforeswap", function (e) {
if ($('#rev_slider').data('slider-layout') == 'fullscreen' && $('body').hasClass('left-nav')) {
var windowHeight = $(window).height();
$('.rev_slider_wrapper, #rev_slider').height(windowHeight);
}
});
revapi.bind('revolution.slide.onchange', function (event, data) {
var logoImg = $('#logo a img');
var logoLight = $('#logo a').data('logo-light');
var logoDark = $('#logo a').data('logo-dark');
var currentSlide = data.slideIndex;
if (revapi.find('li').eq(data.slideIndex - 1).attr('data-color') === 'dark') {
$('body').addClass('transparent-dark');
logoImg.attr('src', logoDark);
}
if (revapi.find('li').eq(data.slideIndex - 1).attr('data-color') === 'light') {
$('body').removeClass('transparent-dark');
logoImg.attr('src', logoLight);
}
});
$('body').on('click', '[data-go-to-slide]', function () {
var goToSlide = $(this).data('go-to-slide');
revapi.revshowslide(goToSlide);
return false;
});
setTimeout(function () {
revapi.revredraw();
}, 400);
}
}
});
So how to properly reinitialise, reload, do something with this slideshow, so it will be re rendered when i visit page via .
If you need any additional informations please let me know and i will provide. Thank you!
i managed to solve it by calling Jquery function in mounted function
example:
export default {
name: 'SlideShow',
methods: {
},
mounted: function () {
// initial start of slide show
revSlider();
}
}
And this is example how my external sliders.js script looks like
// MAIN VARIABLES INITIALIZATION
var revapi;
$(window).resize(function () {
'use strict';
if ($('#rev_slider').data('slider-layout') == 'fullscreen' && $('body').hasClass('left-nav')) {
var windowHeight = $(window).height();
$('.rev_slider_wrapper, #rev_slider').height(windowHeight);
}
});
(function () {
'use strict';
setTimeout(function () {
revSlider();
}, 1000);
}());
stopAtSlide:1
// REVOLUTION SLIDER
function revSlider() {
if ($.fn.revolution && $('#rev_slider').length) {
var revSliderLayout = $('#rev_slider').data('slider-layout') ? $('#rev_slider').data('slider-layout') : 'auto';
......