In created:, my method doesn't work perfectly - css

I'm trying to make a simple vue.js & d3.js code. In the code, I want to plot some charts. For that, I'm trying to make some spaces for charts, by defining a method('add_svg') and run the method in created.
But, the method('add_svg') doesn't work what i intended. I had checked that the method was working, by inserting console.log('Running') for the first part of the method.
I could saw the message, 'Running', but the svg_space, i wanted to insert, wasn't inserted.
But when I UPDATE charts with same method in computed: part, it works.
In the computed: part, it generates some spaces several times, which means that it's working and the method has no problem.
Why is that?
Below is my code:
// GIVES CONSOLE.LOG MESSAGE('RUNNING') BUT DOES NOT APPEND SVG
created () {
console.log("")
this.add_svg() // append svg for chart
this.plot([0, 0]) // basic plot with value = [0, 0]
},
...
// SAME METHOD, BUT IN HERE, IT GIVES ME WHAT I WANTED.
// BUT TO INITIALIZE, I WANT TO RUN THE METHOD IN created: part, not in computed
computed () {
this.add_svg()
this.plot( datum )
}
...
methods: {
add_svg: function () {
console.log("Adding some space for chart")
d3.select('.chart_test2')
.append('svg')
.attr('class', 'svg_chart_test2')
.attr('width', '10px')
.attr('height', '10px')
},
other methods...
}

In Vue, you have to draw d3 charts on the mounted hook, rather than the created hook. You can't draw the chart if the page is not rendered - which is what happens when you use the created hook.
mounted () {
this.add_svg() // append svg for chart
this.plot([0, 0]) // basic plot with value = [0, 0]
}

Related

vue3 vuetifyjs v-color-picker - How to use input event

I'm new in vue3 and using v-color-picker provided by vuetify.js. My goal is that a method is executed when an input event ("new color selected") happens:
<v-color-picker
mode="hexa"
v-model="background_color"
#input="handleChangedColor"
></v-color-picker>
...
methods: {
handleChangedColor() {
console.log("New color selected")
}
},
However, the method handleChangedColor is never triggered. I would be very happy if someone could give me a hint about what I'm doing wrong!
Storing the selectedColor in the variable background_color is working correctly.
The input event is described here https://vuetifyjs.com/en/api/v-color-picker/#props
Thanks for your help.
You've linked the Vuetify 2 documentation, but since you're using Vue 3 I assume you're also using Vuetify 3. Since Vuetify 3.0 the latest documentation is now at https://next.vuetifyjs.com/en/api/v-color-picker/#events
You'll find the new v-color-picker event to listen to is update:modelValue
<v-color-picker
mode="hexa"
v-model="background_color"
#update:modelValue="handleChangedColor"
></v-color-picker>
handleChangedColor(color) {
console.log("New color selected: ", color);
}

How to dynamically alter point radius and style of JSON path in d3?

I need help in dynamically "highlighting" cities on a world map, created using D3 and geoJSON.
I'm working on a spinning globe with 295 city-markers on it. Every 300 millisec, one of these cities need to "be highlighted", meaning 1) change its color and 2) increase its radius (and then stay that way). This gist shows the visual so far: gist example
Steps taken so far:
1) I started with "circle" elements in d3: highlighting was easily done by changing their class (and using CSS styles) and radius. However: the circles remained visible on the "backside" of the globe...
2) To solve the "no circles on back of earth" problem, this post showed me that JSON paths would help: http://bl.ocks.org/PatrickStotz/1f19b3e4cb848100ffd7.
I have now rewritten the code with these paths, and there is correct clipping of the markers on the back of the earth, but now I am stuck in dynamically accessing the radius and style of each city...
Question about changing the radius:
I understand that using path.pointRadius() I can alter the radius of the city markers. However, I want to do this dynamically (every 300msec), and only on a subselection of the markers each time. And that's where I get stuck...
Question about changing the style:
Also I would like to change the color, but assigning styles to the paths confuses me about how to access the JSON "Point" and "path" elements...
Code snippet showing my failed CSS styles attempt:
svg.append('g')
.selectAll("path")
.data(data,function(d,i){ return d.id })
.enter()
.append("path")
.datum(function(d) {
return {
type: "Point",
coordinates: [d.lon, d.lat],
class: "nohighlight" //MY ATTEMPT AT CHANGING CLASS... Not working...
}; })
.attr("class","city") //this class is assigned to the "correct" paths. Can I access them individually??
.attr("d", pathproj);
Code snippet showing the time loop in which the highlighting needs to happen:
//Highlighting the cities one by one:
var city_idx = 0; //data.id starts at 1
//Every 300 msec: highlight a new city:
var city_play = setInterval(function() {
city_idx++;
var filtered = data.filter(function(d) {
return d.id === city_idx;
});
// CHANGE CLASS?
// CHANGE RADIUS?
//Stop when all cities are highlighted
if(city_idx>=geo_data.length){
clearInterval(city_play) //terminates calls to update function within setInterval function.
};
}, 300); // end timer city play setInterval
Full code in block builder:
blockbuilder - globe and city markers
Please do let me know if I can clarify further!
We can do it this way:
To all path belonging to cities give a class
.selectAll("path")
.data(data,function(d,i){ return d.id })
.enter()
.append("path")
.classed("city", true) <--- so all cities point will have class city
Next in the timer block change radius and class dynamically like this:
var city_play = setInterval(function() {
city_idx++;
// Control the radius of ALL circles!
pathproj.pointRadius(function(d,i) {
//your biz logic
if (i < city_idx){
return 4
} else
return 2
});
// CHANGE CLASS?
// CHANGE RADIUS?
//select all elements with class city
d3.selectAll(".city").attr("class",
function(d, i){
if (i < city_idx){
return "city highlight"
} else
return "city"
}).attr("d", pathproj)
var len = d3.selectAll(".city").data().length;
console.log(city_idx, len)
//Stop when all cities are highlighted
if(city_idx>=len){
clearInterval(city_play) //terminates calls to update function within setInterval function.
};
}, 300);
working code here

D3 Invert Selection From Event Listener (this)

I have a visual with many rects, and I have given them the class graph_rects. My goal is when the user clicks on a rect with that class, it will keep that rect the same color but turn all the other graph_rects gray. However my approach did not work and unfortunately it's hard to trouble shoot because there were no errors in the log.
My CSS rule for the graying out:
.graph_rects unselected {
fill:gray;
}
My D3 event listener at rect creation/appending:
.on('click', function(d) {
return d3.selectAll(".graph_rects:not(this)").classed('unselected',true)
})
I'm pretty sure my CSS is ok, my hunch is my d3 logic is not right.
Update
Here are some relevant lines of code that may help piece together why the proposed solutions is not working for me (yet). I am trying to troubleshoot whether or not my matrix of graphs (such as this one) is the culprit by making the selector have redundant ids. So I created a id that has the i and j for the corresponding dimensions as well as i for the index. This way it should be impossible for a rect to have the same id with another rect from a different graph.
.attr('id', function(d,i) {
return String(p.i+p.j)+i
})
Also here is my event listener as per the suggested solution:
.on('click', function(d) {
d3.selectAll('.graph_rects:not(#'+this.id+')').classed('unselected',true)
d3.select(this).classed('unselected',false)
})
Unfortunately I get the following error:
Failed to execute 'querySelectorAll' on 'Document': '.graph_rects:not(#219)' is not a valid selector
What did I not do right I wonder?
First problem, your CSS should be:
.graph_rects.unselected {
fill: gray;
}
But that's not the big issue here. The big issue lies here:
d3.selectAll(".graph_rects:not(this)")
In that line, you're telling D3 to not select any <this></this> element. Of course, such elements don't exist!
There are several ways to achieve what you want, and different coders have their favourite approach (I have mine, which doesn't use the not). However, I'll try to provide a solution keeping that not selector: instead of using not(this), which literally selects something called this, you can select by class or by id (remember, IDs must be unique). For example:
d3.selectAll(".graph_rects:not(#" + this.id + ")")
Here is an example, click the bars:
var svg = d3.select("svg");
var rects = svg.selectAll("planck")
.data(d3.range(10))
.enter()
.append("rect")
.attr("class", "graph_rects")
.attr("id", function(d, i) {
return "rect" + i
})
.attr("x", function(d, i) {
return i * 25
})
.attr("y", 0)
.attr("width", 20)
.attr("height", 150)
.attr("fill", "firebrick")
.on('click', function() {
d3.selectAll(".graph_rects:not(#" + this.id + ")").classed('unselected', true);
d3.select(this).classed("unselected", false)
})
.graph_rects.unselected {
fill: gray;
}
.graph_rects {
cursor: pointer;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

Why are not all Google Map Tiles rendered on the initial load of an AngularJS app?

Working on a Google Map app built with AngularJS.
Currently deployed sandbox: http://of.xchg.com/
Click Map link and you will notice only ONE tile IF ANY are rendered.
If you then RESIZE the browser window, THEN the rest of the map tiles will render completely.
Here is the git project: https://github.com/LarryEitel/of4
Why are not all Google Map Tiles rendered?
Is there a way to test for complete rendering of tiles?
Is there a way to force re-rendering of all map tiles?
Call this function in your map controller:
google.maps.event.trigger(map, 'resize');
That should do the trick.
I found this problem when trying to re-center the map after the view loaded. There would be a single tile in the top left corner.
I noticed that it was centering the map at the topleft of the div (0,0), and figured that it must be measuring the div before it was visible. This would mean the dimensions were 0px, 0px and so to center the map would mean placing a single tile at (0,0).
I tried the solution of triggering the resize event
google.maps.event.trigger(map, 'resize');
and that almost worked - it filled the div with tiles, but it was still centered at (0,0).
What worked was to wrap the re-center code in a $timeout(). This ensures that the div is fully loaded and correctly sized before the code runs. Now it works perfectly.
$timeout(function() {
// still need this.
google.maps.event.trigger(map, 'resize');
map.setCenter(53, -6);
});
After a lot of trial and error, I found a workaround. By merely injecting the GoogleMap Service into the app run command, it successfully rendered the complete map. I ALSO had to make the default '/' route show the map page. Anything else I would do that involved trying to switch from a home (non-map) page to the map page would result in a partially rendered map. :(
Perhaps I or someone will suggest a more elegant solution. :)
// Generated by CoffeeScript 1.6.1
(function() {
'use strict';
angular.module('of4App', []).config(function($routeProvider) {
return $routeProvider.when('/menu', {
templateUrl: 'views/menu.html',
controller: 'MainCtrl'
}).when('/list', {
templateUrl: 'views/list.html',
controller: 'MainCtrl'
}).when('/map', {
templateUrl: 'views/map.html',
controller: 'MapCtrl'
}).when('/about', {
templateUrl: 'views/main.html',
controller: 'MainCtrl'
}).otherwise({
redirectTo: '/map'
});
}).run(function($rootScope, $location, GoogleMap) {
var rootScope;
rootScope = $rootScope;
rootScope.navBarHeight = 40;
return rootScope.mapShown = function() {
var mapShown;
mapShown = $location.path().indexOf('/map') > -1;
return mapShown;
};
});
}).call(this);

how to select feature by drawing a line in openlayers?

There is one option in openlayers selecting features under the box. But, I want to select the features when I draw line (draw with shift key down-free hand drawing). In my script I already implemented drawing and selecting options. I can draw line and select (multiple) features independently. Now, I want to merge this two. I want to select those features data which are touched by my drawn line. Is there any sample example available?
Here, I have given sample code -
//Selection property---------------------------------------
var selectControl = new OpenLayers.Control.SelectFeature(
[vectorLayer],
{
clickout: true, toggle: true,
multiple: true, hover: false,
toggleKey: "ctrlKey", // ctrl key removes from selection
multipleKey: "shiftKey" // shift key adds to selection
}
);
map.addControl(selectControl);
selectControl.activate();
var draw = new OpenLayers.Control.DrawFeature(
vectorLayer, OpenLayers.Handler.Path,
{displayClass: "olControlDrawFeaturePoint", title: "Draw Features", handlerOptions: {holeModifier: "altKey"}}
);
Thanks, in advance.
You have to register event "sketchcomplete" that will run over all features in layer-bo-be-selected and check if it has shared geometry with line sketched.
Something like this, unfortunately I can't test it now.
vectorLayer.events.register('sketchcomplete', vectorLayer, sketchCompleteFunc);
function sketchCompleteFunc(obj) {
for (var i=0;i<layer-to-be-selected.features.length;i++) {
if (layer-to-be-selected.features[i].geometry.intersects(obj.geometry)) {
selectControl.select(layer-to-be-selected.features[i])
}
}
}

Resources