So I am trying to get a dat.GUI placed on the upper right corner of the canvas using the custom placement tutorial:
Here is a codepen showing the not working custom placement:
http://codepen.io/eternalminerals/pen/avZBOr
I am trying to use the custom placement property because the autoplaced dai.GUI on this page http://eternalminerals.com/testa/ is un-clickable. I think if I custom placed it to the canvas instead of the page it should work.
I tried:
var gui = new dat.GUI({ autoPlace: false });
var customContainer = document.getElementById('my-gui-container');
customContainer.appendChild(gui.domElement);
on both the codepen and the live site, where 'my-gui-container' is 'canvas', but whenever I do this, the dat.GUI disappears completely. Maybe I have to wrap the canvas in a div? I will continue to tinker with this dat.GUI and keep you posted.
Thanks.
So this is a duplicate question: How do I change the location of the dat.gui dropdown?
I simply used the moveGui div and attached the dat.GUI to the moveGui div and used CSS to move it around. The codepen is now working!! http://codepen.io/eternalminerals/pen/avZBOr
html:
<canvas id="canvas"></canvas>
<div class = 'moveGUI'>
</div>
css:
.moveGUI{
position: absolute;
top: 13.1em;
right: -1em;
}
js:
var FizzyText = function() {
this.message = 'dat.gui';
this.speed = 0.8;
this.displayOutline = false;
this.explode = function() { console.log('test'); };
// Define render logic ...
};
$(document).ready(function( $ ) {
var text = new FizzyText();
var gui = new dat.GUI({ autoPlace: false });
gui.add(text, 'message');
gui.add(text, 'speed', -5, 5);
gui.add(text, 'displayOutline');
gui.add(text, 'explode');
gui.domElement.id = 'canvas';
var customContainer = $('.moveGUI').append($(gui.domElement));
});
Related
Does anyone have a method for adding a title to a leaflet layers control? Just a line of text, for example "Available layers." Ideally I'd like to add a link to the text as well.
I thought it would be simple, but I haven't been able to find a solution. I tried methods similar to this question (radio button/checkbox remains after adding "dummy" layer) and this question (adds div to end of layers, seems more complex than my needs). Unfortunately with my experience level, I haven't been able to connect the dots. Any suggestions?
Input Elements in Layer Control are present under
.leaflet-control-layers-overlays
$(".leaflet-control-layers-overlays").prepend("<label>Available layers</label>");
You can also assign a class and add some styling on this. This is not good solution but hope it helps you.
#Leaflet1.7
Here is the vanilla JS minimal solution.
// 0. Your's WMS layers:
var fooLayers = {
"Aaa" : ign_ari,
"Bbb" : ign_cri,
"Ccc" : ign_grvi
};
// 1. start with Control
var fooLegend = L.control({position: 'topleft'});
fooLegend.onAdd = function () {
var div = L.DomUtil.create('div');
// here is Your part:
div.innerHTML = '<span class='your-class'>Your Title Text</span>';
return div;
};
fooLegend.addTo(map);
var fooCtrl = L.control.layers(fooLayers, null,
{collapsed : false, position: 'topleft'})
.addTo(map);
//
// Nothing unusual, until now:
var fooCtrlDiv = fooCtrl.getContainer();
fooCtrlDiv.insertBefore(fooLegend.getContainer(), fooCtrlDiv.firstChild);
You can assign a title attribute to the control. Here's an obviously incomplete snippet from a current project:
// Add settings button
var atlasMapSettings = L.Control.extend({
options: {
position: 'topleft'
},
onAdd: function (map) {
var control = L.DomUtil.create('div', 'leaflet-bar leaflet-control leaflet-control-custom atlas-settings-control closed');
var icon = L.DomUtil.create('div', 'fa fa-gear closed', control);
var content = L.DomUtil.create('div', 'control-content empty', control);
$(icon).attr('title', 'Map settings');
Leaflet 1.7: Addition to #Mruk's answer: If you want to use collapsed: true, then you have to dig a little bit deeper in the DOM tree:
const fooCtrlDiv = fooCtrl.getContainer();
fooCtrlDiv
.querySelector('.leaflet-control-layers-list')
.insertBefore(
fooLegend.getContainer(),
layerControlDiv.querySelector('.leaflet-control-layers-list').firstChild
);
Im using joint js library to create a diagram inside html, but i need it to be responsive as mi site.Thing is, i have it inside a div with a java class that open down and closes up with this code :
$('.open-down-up').click(function(){
var nameMore = $(this).attr("name");
var valMore = $(this).attr("value");
if(valMore == 0){
$(this).find('span').empty();
$(this).find('span').append("▼");
$('div[id='+nameMore+']').slideDown("normal");
$(this).attr("value","1");
}else if(valMore == 1){
$(this).find('span').empty();
$(this).find('span').append("►");
var n = nameMore.indexOf("process_process");
$('div[id='+nameMore+']').slideUp("normal", function(){
var n = nameMore.indexOf("process_process");
if(n > -1){
hide_panel_all();
}
});
$(this).attr("value","0");
}
});
SO, i already tried things like :
var graph = new joint.dia.Graph;
var paper = new joint.dia.Paper({
el: $('#modelCanvas'),
gridSize: 10,
height: $('#modelCanvas').height(),
width: $('#modelCanvas').width(),
gridSize: 1,
model: graph,
});
But it doesn't work...any idea or approach i can apply ??
Thanks in advance.
I found a way so it may be helpfull for someone who need it (for a resizing responsive):
It's necessary to scale the entire paper along with the window, so, we create a javascript event on it:
window.onresize = function(event) {
paper.setDimensions($('#your_div_id').width());
paper.scaleContentToFit({minScaleX: 0.3, minScaleY: 0.3, maxScaleX: 1 , maxScaleY: 1});
};
Using joint js properties whe resize the canvas along with the div based on that event but only affecting width, then set a max scale for X and Y axis. You can of course, adapt it of make conditions on it as you may need.
Hope it helps as for me !
I have worked with JointJS now for a while, managing to create elements with HTML in them.
However, I am stuck with another problem, is it possible to place HTML code, like
href, img etc, on a JointJS link and how do I do this?
For example, if I have this link, how do I modify it to contain HTML:
var link = new joint.dia.Link({
source: { id: sourceId },
target: { id: targetId },
attrs: {
'.connection': { 'stroke-width': 3, stroke: '#000000' }
}
});
Thank you!
JointJS doesn't have a direct support for HTML in links. However, it is possible to do with a little bit of JointJS trickery:
// Update position of our HTML whenever source/target or vertices of our link change:
link.on('change:source change:target change:vertices', function() { updateHTMLPosition(link, $html) });
// Update position of our HTML whenever a position of an element in the graph changes:
graph.on('change:position', function() { updateHTMLPosition(link, $html) });
var $html = $('<ul><li>one</li><li>two</li></ul>');
$html.css({ position: 'absolute' }).appendTo(paper.el);
// Function for updating position of our HTML list.
function updateHTMLPosition(link, $html) {
var linkView = paper.findViewByModel(link);
var connectionEl = linkView.$('.connection')[0];
var connectionLength = connectionEl.getTotalLength();
// Position our HTML to the middle of the link.
var position = connectionEl.getPointAtLength(connectionLength/2);
$html.css({ left: position.x, top: position.y });
}
Bit of an old question, but thought I'd add some more ideas. You can add extra svg markup to the label in a link if you like by extending the link object and then setting attributes where needed. For example:
joint.shapes.custom.Link = joint.dia.Link.extend({
labelMarkup: '<g class="label"><rect /><text /></g>'
});
This code overrides the markup for the label, so you can add extra elements in there. You can also update attributes on these elements by:
link.attr('text/text', "new text");
However hyperlinks won't work (at least I haven't got them working in Chrome) and I believe this is because Jointjs listens for all events in the model. So what you should do is use inbuilt events in Jointjs to listen for connection clicks:
paper.on('cell:pointerclick', function(cellView, evt, x, y){
console.log(cellView);
});
I am trying to use the pie chart from Chart.js (http://www.chartjs.org/docs/#pieChart-exampleUsage). Everything works smooth, but the animation happens as soon as the page loads, but since the user has to scroll down to see the chart, they won't see the animation. Is there anyway I can make the animation to start only when scrolled to that position? Also if possible, is it possible to animate everytime when that chart becomes into view?
My code is as follows:
<canvas id="canvas" height="450" width="450"></canvas>
<script>
var pieData = [
{
value: 30,
color:"#F38630"
},
{
value : 50,
color : "#E0E4CC"
},
{
value : 100,
color : "#69D2E7"
}
];
var myPie = new Chart(document.getElementById("canvas").getContext("2d")).Pie(pieData);
</script>
You can combine the check for whether something is viewable with a flag to keep track of whether the graph has been drawn since it appeared in the viewport (though doing this with the plugin bitiou posted would be simpler):
http://jsfiddle.net/TSmDV/
var inView = false;
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return ((elemTop <= docViewBottom) && (elemBottom >= docViewTop));
}
$(window).scroll(function() {
if (isScrolledIntoView('#canvas')) {
if (inView) { return; }
inView = true;
new Chart(document.getElementById("canvas").getContext("2d")).Pie(data);
} else {
inView = false;
}
});
Best to use deferred plugin
https://chartjs-plugin-deferred.netlify.com/
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-deferred#1"></script>
new Chart(ctx, {
// ... data ...
options: {
// ... other options ...
plugins: {
deferred: {
xOffset: 150, // defer until 150px of the canvas width are inside the viewport
yOffset: '50%', // defer until 50% of the canvas height are inside the viewport
delay: 500 // delay of 500 ms after the canvas is considered inside the viewport
}
}
}
});
I don't know if you could do that, I had the same issue and resolved it without any plugin in this simple way, check out:
$(window).bind("scroll", function(){
$('.chartClass').each(function(i){
var dougData = [
{value: 100, color:"#6abd79"},
{value: 20, color:"#e6e6e6"}
];
var graphic = new Chart(document.getElementById("html-charts").getContext("2d")).Doughnut(dougData, options);
$(window).unbind(i);
});
});
I had the same problem with Chart.js and found a really great solution.
There is a package on GitHub that is called ChartNew.js by FVANCOP.
He expanded it and added several functions.
Look at the sample, the charts are drawn by scrolling down.
Responsible is the statement
dynamicDisplay : true
Using IntersectionObserver is the more modern approach, and gives you the ability to choose how much of the element must be visible before triggering an event.
A threshold of 0 means it will trigger if any part of the element is visible, while a threshold of 1 means the entire element must be visible.
It performs better than listening to scroll, and will only fire once when the element transitions from hidden to visible, even while you are continuously scrolling. And it also works if the page content changes due to other events, such as other content being hidden/shown, or window resize, etc.
This is how I made a radial chart that animates every time at least 20% of it appears into view:
const options = {
series: [75],
chart: {
type: 'radialBar',
},
};
const chart = new ApexCharts(document.querySelector("#chart"), options);
chart.render();
const observer = new IntersectionObserver(function(entries) {
if (entries[0].isIntersecting === true) {
chart.updateSeries([0], false); // reset data to 0, then
chart.updateSeries([75], true); // set original data and animate
// you can disconnect the observer if you only want this to animate once
// observer.disconnect();
}
}, { threshold: [0.2] });
observer.observe(document.querySelector("#chart"));
This is what you want:
Check if element is visible after scrolling
Next time please check if there's already an answer ;)
Alternatively: jquery.appear
I'm trying to get an overlay in google maps api v3 to appear above all markers. But it seems that the google api always put my overlay with lowest z-index priority. Only solution i've found is to iterate up through the DOM tree and manually set z-index to a higher value. Poor solution.
I'm adding my a new div to my overlay with:
onclick : function (e) {
var index = $(e.target).index(),
lngLatXYposition = $.view.overlay.getProjection().fromLatLngToDivPixel(this.getPosition());
icon = this.getIcon(),
x = lngLatXYposition.x - icon.anchor.x,
y = lngLatXYposition.y - icon.anchor.y
$('<div>test</div>').css({ left: x, position: 'absolute', top: y + 'px', zIndex: 1000 }).appendTo('.overlay');
}
I've tried every property I could think of while creating my overlay. zIndex, zPriority etc.
I'm adding my overlay with:
$.view.overlay = new GmapOverlay( { map: view.map.gmap });
And GmapOverlay inherits from new google.maps.OverlayView.
Any ideas?
..fredrik
If anyone was having the same problem as I was, here is my problem and solution:
I needed an OverlayView which would add tooltips to markers, but my popup overlay kept showing behind the markers.
I implemented a subclass of the OverlayView as per the Google documentation:
https://developers.google.com/maps/documentation/javascript/customoverlays
When you write your custom OverlayView.prototype.onAdd function, you need to specify to which Pane to attach your overlay. I just copied the code without actually reading the surrounding explanation.
In their code, they attach the overlay to the overlayLayer pane:
var panes = this.getPanes();
panes.overlayLayer.appendChild(div);
But there are many different MapPanes you can use:
"The set of panes, of type MapPanes, specify the stacking order for different layers on
the map. The following panes are possible, and enumerated in the order in which they are stacked from bottom to top:"
MapPanes.mapPane (Level 0)
MapPanes.overlayLayer (Level 1)
MapPanes.markerLayer (Level 2)
MapPanes.overlayMouseTarget (Level 3)
MapPanes.floatPane (Level 4)
I wanted the overlay to hover over all other info on the map, so I used the floatPane pane and problem solved.
So, instead of :
this.getPanes().overlayLayer.appendChild(div)
you use this :
this.getPanes().floatPane.appendChild(div);
You can't change the zIndex of an OverlayView (it has no such property), but it holds panes that contains DOM nodes. That's where you can use the z-index property;
...
lngLatXYposition = $.view.overlay.getPanes().overlayLayer.style['zIndex'] = 1001;
...
In order to be able to play around with the paneType of the mapLabel class, I added a paneType property to the MapLabel class from google utility library (https://code.google.com/p/google-maps-utility-library-v3/source/browse/trunk/maplabel/src/maplabel.js?r=303).
This is usefull to make the label not to be hidden by a polyline.
Please find the code additions to the mapLabel.js file.
MapLabel.prototype.onAdd = function() {
var canvas = this.canvas_ = document.createElement('canvas');
var style = canvas.style;
style.position = 'absolute';
var ctx = canvas.getContext('2d');
ctx.lineJoin = 'round';
ctx.textBaseline = 'top';
this.drawCanvas_();
var panes = this.getPanes();
if (panes) {
// OLD: panes.mapPane.appendChild(canvas)
var paneType = this.get('paneType');
panes[paneType].appendChild(canvas);
}
};
MapLabel = function (opt_options) {
this.set('fontFamily', 'sans-serif');
this.set('fontSize', 12);
this.set('fontColor', '#000000');
this.set('strokeWeight', 4);
this.set('strokeColor', '#ffffff');
this.set('align', 'center');
this.set('zIndex', 1e3);
this.set('paneType', 'floatPane');
this.setValues(opt_options);
}
Sample code using the paneType:
var mapLabel = new MapLabel({
text: segDoc.curr_value.toFixed(0),
position: new google.maps.LatLng(lblLat, lblLng),
map: map.instance,
fontSize: 12,
align: 'center',
zIndex: 10000,
paneType: 'floatPane',
});
Thanks!
Setting z-index to 104 for the overLay layer seems to be the "magic" number" if you care about interacting with the markers (i.e. dragging markers). Any higher than 104 and you can not interact with the markers. Wondering if there is a less brittle solution...
Use panes.overlayMouseTarget.appendChild
If you want to allow your layer to be targetable through mouse clicks (and use events such as "click" or CSS pseudo ::hover) then you should add your overlay to the map using overlayMouseTarget
var panes = this.getPanes();
panes.overlayMouseTarget.appendChild(this.div_);
Also see:
https://developers.google.com/maps/documentation/javascript/reference?csw=1#MapPanes
Disclaimer: this is a dodgy solution that may stop working at any time and you definitely shouldn't use this in production.
For those looking for a quick and dirty solution, this CSS worked for me:
.gm-style > div:first-child > div:first-child > div:nth-child(4) {
z-index: 99 !important;
}
Use at your own risk!