This question already has an answer here:
How can I connect two HTML elements by drawing lines in a background canvas?
(1 answer)
Closed 5 years ago.
I'm creating a tree like structure. I have created the numbers in a circle using html badges. Now I want to draw lines from one element to another element. I have tried using an image which is like left diagonal and right diagonal. But it is not working.
This is my html for creating Badges:
<span id="0" class="cl w3-badge">0</span><br><br><br><br>
<span id="1" class="cl w3-badge">0</span>
<span id="2" class="cl w3-badge">0</span>
This is my javascript:
var data = [];
data.push(5);
data.push(6);
data.push(4);
$('.w3-badge').each(function(i, obj) {
document.getElementById(i).innerHTML = data[i];
});
This is image of left line
Can someone help me??
I'm trying to get my final tree to be like this:
Final tree
using svg is the best option for those kind of thing,
i wrote a function below that do exactly what you need.
you have tho to rewrite it to your needs.
use full page to see the result right.
function drawLine(div1, div2){
var svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
svgPath = document.createElementNS("http://www.w3.org/2000/svg", "path");
var div1Offset = div1[0].getBoundingClientRect();
var div2Offset = div2[0].getBoundingClientRect();
var pathNr = "";
pathNr = "M"+ (div1Offset.width + div1Offset.left)+ " " + ((div1Offset.top + div1Offset.height) / 2)
pathNr += "h" +( div2Offset.left)
pathNr += "v" +(div2Offset.top)
pathNr += "h" +( -div2Offset.left )
svgPath.setAttribute("d", pathNr);
svgPath.setAttribute("stroke", "red");
svgPath.setAttribute("stroke-width", "1");
svgPath.setAttribute("fill", "white");
svgPath.setAttribute("id", "test");
svg.appendChild(svgPath);
$("body").append(svg);
}
$(document).ready(function(){
drawLine($(".box_1"), $(".box_2"))
});
.box{
width:150px;
height:150px;
margin:30px;
background:black;
}
svg{
position:absolute;
left:0; top:0;
width:100%;
height:100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='box box_1'></div>
<div class='box box_2'></div>
Related
I am trying to write code that resizes an SVG overlay on top of an image. The server I am working with returns both the image and via an API, a list of polygon points I need to overlay on top of the image.
This is what it should look like (the image below is a correctly aligned SVG layer). The image size is 1280x720 (I've scaled it down)
What I need to do in my app (ionic v1 app) is to make sure the SVG overlay resizes as the browser window resizes and it seems to be very hard. Here is my approach:
I am trapping a window resize event and when the image is resized, I scale the SVG polygon points relative to the size of the drawn window as it seems there is really no way to "automatically" scale the SVG by the browser like it does with an image.
Here is my code pen as you see it doesn't work as intended when I rescale (and for that matter in when its full size the overlays are not accurate). The overlays don't look accurate and when I resize it all messed up. Can someone help?
Given SO needs a code block for codepen links here it is, but its just easier to look at the codepen if you want to run it
CSS:
.imagecontainer{position:relative; margin:0 auto;}
.zonelayer
{
position:absolute;
top:0;
left:0;
background:none;
}
.zonelayer polygon {
fill-opacity: 0.25;
stroke-width: 2px;
}
.Active {
stroke: #ff0000;
fill: #ff0000;
}
HTML code:
<ion-content>
image:{{disp}}<br/>
<small>points: <span ng-repeat="item in zoneArray">{{item}}</span></small>
<div class="imagecontainer">
<img id="singlemonitor" style="width:100vw; height:100vh;object-fit:contain" ng-src="http://m9.i.pbase.com/o9/63/103963/1/164771719.2SfdldRy.nphzms.jpeg" />
<div class="zonelayer">
<svg ng-attr-width="{{cw}}" ng-attr-height="{{ch}}" class="zonelayer" ng-attr-viewBox="0 0 {{cw}} {{ch}}">
<polygon ng-repeat="item in zoneArray" ng-attr-points="{{item}}" class="Active"/> </polygon>
</svg>
</div>
</div>
</ion-content>
JS controller:
window.addEventListener('resize', liveloaded);
liveloaded();
// credit: http://stackoverflow.com/questions/41411891/most-elegant-way-to-parse-scale-and-re-string-a-string-of-number-co-ordinates?noredirect=1#41411927
function scaleCoords(string, sx, sy) {
var f = [sx, sy];
return string.split(' ').map(function (a) {
return a.split(',').map(function (b, i) {
return Math.round(b * f[i]);
}).join(',');
}).join(' ');
}
function liveloaded()
{
$timeout (function () {
console.log ("IMAGE LOADED");
var img =document.getElementById("singlemonitor");
//var offset = img.getBoundingClientRect();
$scope.cw = img.clientWidth;
$scope.ch = img.clientHeight;
$scope.vx = img.offsetWidth;
$scope.vy = img.offsetHeight;
var rect = img.getBoundingClientRect();
//console.log(rect.top, rect.right, rect.bottom, rect.left);
$scope.disp = img.clientWidth+ "x"+img.clientHeight + " with offsets:"+$scope.vx+"/"+$scope.vy;
$scope.zoneArray = [
"598,70 700,101 658,531 516,436",
"531,243 687,316 663,593 360,717 191,520",
"929,180 1108,248 985,707 847,676",
"275,17 422,45 412,312 271,235",
];
var ow = 1280;
var oh = 720;
for (var i=0; i < $scope.zoneArray.length; i++)
{
var sx = $scope.cw/ow;
var sy = $scope.ch/oh;
$scope.zoneArray[i] = scaleCoords($scope.zoneArray[i],sx,sy);
console.log ("SCALED:"+$scope.zoneArray[i]);
}
});
}
There are a couple of issues with your code.
The main problem is you can't use ng-attr-viewBox, because angular will "normalise" the attribute to lower case. It turns the attribute into viewbox (lower case B) which is (currently) invalid. viewBox is case sensitive.
The solution is to use a special trick of Angular to preserve camel-case. If you use ng-attr-view_box, it will generate the correctly camel-cased attribute name of viewBox.
<svg width="100vw" height="100vh" class="zonelayer" ng-attr-view_box="0 0 {{cw}} {{ch}}">
The other thing is that you are using the wrong width and height values for the viewBox. You need to use the natural/intrinsic image dimensions in your viewBox.
$scope.cw = img.naturalWidth;
$scope.ch = img.naturalHeight;
Link to updated code pen
I've seen similar questions asked before but none of them really helped in my situation. To boil it down I, a noobie, am trying to change an html background color to a variable that was created in a js script and I'm not sure quite how to do this. I want "color" to be used for the background color. h, m, s are hours minutes and seconds. I'm pulling these from the computer and it is working fine printing it. Here is something I found that is nearly identical to what I want to do www.jacopocolo.com/hexclock/
JS
if (h<=9) {h = '0'+h};
if (m<=9) {m = '0'+m};
if (s<=9) {s = '0'+s};
var color = '#'+h+m+s;
$("div.background").css("background-color", color );
HTML
<style>
.background {
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
I've tried making a div for the background (shown above) but it doesn't seem to be working. In the end all I'm really set on is this part of it
if (h<=9) {h = '0'+h};
if (m<=9) {m = '0'+m};
if (s<=9) {s = '0'+s};
var color = '#'+h+m+s;
Can someone tell me how to properly do this or even just point me in the general direction? Any help would be greatly appreciated.
I tried it, and it works fine.
$(document).ready(function(){
var h = 0;
var m = 9;
var s = 20;
if (h<=9) {h = '0'+h}
if (m<=9) {m = '0'+m};
if (s<=9) {s = '0'+s};
var color = '#'+h+m+s;
console.log('color' + color);
console.log("Original Color " + $("div.background").css('background-color'));
$("div.background").css("background-color", color );
console.log("Updated Color " + $("div.background").css('background-color'));
});
<html>
<title>Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="app.js"></script>
<style>
.background {
width: 100%;
height: 100%;
position: absolute;
vertical-align: middle;
}
</style>
</head>
<body>
<div class="background">hello world</div>
</body>
</html>
The problem in your code is probably that a color parameter pre-pended with '#' must be given in hexadecimal coordinates:
red=10, green=20 and blue=40 should be written like this:
#0A1428
So, you have to convert first to hexadecimal each coordinate like this:
var h = h.toString(16);
var m = m.toString(16);
var s = s.toString(16);
Then, perform the zero left-padding, and so.
I'm attempting to recreate and update this fiddle. I was able to create a separate chart but unable to achieve the second progress.
The second chart
<div id="radial-progress-vha">
<div class="circle-vha">
<div class="mask-vha full-vha">
<div class="fill-vha"></div>
</div>
<div class="mask-vha half-vha">
<div class="fill-vha"></div>
<div class="fill-vha fix-vha"></div>
</div>
<div class="shadow-vha"></div>
</div>
<div class="inset-vha">
<div class="percentage-vha">22.17</div>
</div>
</div>
My understanding is that each graph should be unique therefore I copied the original css with a different name. This is where it fell apart.
The js
var transform_styles = ['-webkit-transform', '-ms-transform', 'transform'];
window.randomize = function() {
var rotation = Math.floor((180)*.123);
var fix_rotation = rotation;
for(i in transform_styles) {
$('.circle .fill, .circle .mask.full').css(transform_styles[i],'rotate(' + rotation + 'deg)');
//$('.circle .mask.left').css(transform_styles[i], 'rotate(' + rotation + 'deg)');
$('.circle .fill.fix').css(transform_styles[i],'rotate(' + fix_rotation + 'deg)');
}
}
setTimeout(window.randomize, 200);
$('#radial-progress-vha');
I have a working fiddle: http://jsfiddle.net/uouxcLbd/
Your main issues were
you didn't need to duplicate the definition of transform-styles
The $('#radial-progress-va'); and $('#radial-progress-vha'); lines were unnecessary
The second definition of window.randomize needed a different name
The second randomize function needed to use your css classes with the -vha suffix
You made a typo in the CSS - it was missing a single . so the .fill-vha selector didn't work
I am currently using this method to have a slidehow of promo images, everything working nice, but i would like to add a few things to it, like image transition (fade in) and little dots on the right bottom corner showing which image i am viewing and have the ability to switch to another image
How can i do this?
I am working on the circle buttons now, and the code looks like this so far
<div id="feature-image">
<img id="promo-image" src="images/pentagg.jpg" width="100%" height="800px" name="slide" />
<script type="text/javascript">
var step=1;
var imagesTotal= 2;
var circleDiv;
function slideit()
{
document.images.slide.src = eval("image"+step+".src");
if(step<imagesTotal)
step++;
else
step=1;
setTimeout("slideit()",5000);
}
slideit();
function createCircles()
{
for (i=0; i<imagesTotal; i++) {
circleDiv = document.createElement('div');
circleDiv.className = 'results';
circleDiv.style.width = '32px';
circleDiv.style.height = '32px';
circleDiv.style.backgroundColor = '#ff4444';
circleDiv.innerHTML = '<span class="msg">Hello world.</span>';
document.getElementsByTagName('feature-image')[0].appendChild(circleDiv);
//document.getElementsByTagName('body')[0].appendChild(circleDiv);
}
}
createCircles();
</script>
</div>
Here's a partial answer
You can use a CSS "Hack" of sorts to position the circles at the bottom of your div by making the wrapping div have position: relative and the inner elements have position: absolute
http://jsfiddle.net/wWunK/
I am trying to make a application one of the module is displaying a multiple canvas at same location. This canvas is used to display graph. I have 2 buttons: pie and bar:
When I click on pie it should display pie chart. and when I click on bar it should display bar graph. I am using following approach:
rendering 2 canvas at same location.
.wrapper canvas {
position: absolute;
top: 0px;
left: 0px;
visibility:hidden;
}
In pie button i'm hiding bar chart and display pie. Same goes for bar button.
$("input[type='radio']").change(function(){
var whChart = $('input[name="radio-view"]:checked').val();
var canpie = document.getElementById('pie4');//$("canvas[name='pie4'][0]");
var canbar = document.getElementById('pie41');//$("canvas[name='pie4'][0]");
if(whChart == "Pie"){
RGraph.Effects.jQuery.Snap(pie4);
canpie.style.visibility='visible';
canbar.style.visibility='hidden';
}
else if( whChart == "Bar"){
RGraph.Effects.jQuery.Snap(pie41);
canpie.style.visibility='hidden';
canbar.style.visibility='visible';
}
});
html file
<div class="wrapper" style="text-align:center;">
<canvas id="pie4" width="450" height="250" style="background:black; z-index: 1; visibility:visible; ">[No canvas support]</canvas>
<canvas id="pie41" width="450" height="250" style="background:red; z-index: 2;">[No canvas support]</canvas>
</div>
But the problem is these 2 canvas are displaying one below another. Not at the same place overlapping.
I have checked other post related to double buffering and also tried other options like making 1st canvas height and width to '0', but it doesn't seems to work. Could please someone help in this matter. Since I'm very new to this JavaScript.
p.s : Sorry this is my first post. I know there are lot of mistakes and information missing. If you let me know if anything else needed I will provide.
The problem is visibility keeps the space, you want to use display which does not maintain the space.
var pieState = (whChart == "Pie") ? "block" : "none";
var barState = (whChart == "Bar") ? "block" : "none";
canpie.style.display = pieState;
canbar.style.display = barState;
Please see this stackoverflow question for an explanation.
Since you seem to be using jQuery, you could just use jQuery's show()/hide() or toggle()