When changing height of rect with transition, lowest rect sometimes get smeared - html

I'm using angular to create dynamic charts. I use css 'transition' in order to give it an effect, that the charts are going up. But when I initialize the charts value, the charts are indeed go up very nicely, but for some reason the chart with the lowest value sometimes gets smeared.
Any ideas why?
I attched a photo to show the unwanted outcome.
Left Chart Gets Smeared http://jsfiddle.net/Lvc0u55v/8846/
Update:
Here is a little example of how it suppose to look. Run it a few times to see it happens. You know what is crazy? I ran it a few times on different computers on Chrome with same version and I saw the error happens only on one of them. Does it might have something to do with the graphic card?
http://jsfiddle.net/Lvc0u55v/8846/
Angular:
var app = angular.module("myApp", [])
app.controller("MyCtrl", function ($scope, $timeout) {
$scope.charts = [{height:0, x:10, width:80, color:"red"},
{height:0, x:110, width:80, color:"blue" },
{height:0, x:210, width:80, color:"purple"},
{height:0, x:310, width:80, color:"green"}]
$timeout(function(){
for(var i = 0;i<4;i++){
$scope.charts[i].height = 200 + Math.random() * 100;
}
}, 1)
})
Html:
<div ng-app="myApp" ng-controller="MyCtrl">
<svg width=400 height=300>
<rect ng-repeat="chart in charts" ng-attr-height="{{chart.height}}" ng-attr-width={{chart.width}} ng-attr-x="{{chart.x}}" fill={{chart.color}} stroke=black stroke-width:1px></rect>
</svg>
</div>
CSS:
rect{
transition: 0.5s;
}
svg{
transform:rotateX(180deg)
}

Related

how to make a js textarea draggable

I have a textarea generated with the bellow js code, I also have a button that creates additional text areas when clicked, I NEED to make each text area draggable, Ussually because the "id" is "myForm" it should become draggable using jquery $('#myForm') but it does not work, I have try all forms but it does not work. I also have check similar questions but not luck... I will appreciate if some one can help me out. in the folder I have the Html, The css and all jquery libraries working Ok.
I check with the alert box.
Note: all I need is a textarea with a button to add as many additional text areas and this areas to be draggable, the code to generate this text areas can be any code. In case there is a easier way to accomplish the same thing... Thank you in advance.
function myFunction() {
var x = document.createElement("FORM");
x.setAttribute("id", "myForm");
document.body.appendChild(x);
var y = document.createElement("TEXTAREA");
document.getElementById("myForm").appendChild(y);
}
Is HTML5 Drag and Drop what you are looking for?
All you need to do is define draggable=true in your element and code the relevant ondragstart and ondragend logic. This works with both vanilla JS and frameworks like React.
Made for you kindly however dosn't work in this editor
var new_offset = {top:30, left:40};
var new_width = 200;
var new_height = 150;
var newElement$ = $('<div><textarea id="textarea"></textarea></div>')
.width(new_width)
.height(new_height)
.draggable({
cancel: "text",
start: function (){
$('#textarea').focus();
},
stop: function (){
$('#textarea').focus();
}
})
.resizable()
.css({
'position' : 'absolute',
'background-color' : 'gray',
'border-color' : 'black',
'border-width' : '1px',
'border-style' : 'solid'
})
.offset(new_offset)
.appendTo('body');
textarea {
height:100%;
background-color:whit;
width:100%;
resize:none; border:none;
padding:0px; margin:0px;
}
div { padding:0px; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.js"></script>
I hacked it and piggy tailed to a span element this way the span element is easy to make draggable with jquery, The textarea is not draggable but it has to follow the span element THUS is draggable.
The span element has the class= "drag",then I used the jquery $('.drag').draggable and that made the whole trick. Dirty code BUT it works 100% the way I needed.

Html2canvas - Only half of the content shows in the pdf

Using Html2canvas, jsPdf, and angularjs to take a screen shot of a portion of my webpage to show as a pdf preview. I was able to successfully export the content to the pdf, but it only shows half of the content. What can I do to fix this?
Here is the button that creates the pdf. (rollup.html)
<button ng-click="genPDF()">PDF Test</button>
Within the controller, I used the html2canvas function (rollup.js)
Here I believe 'document.body.appendChild' may be the key because when it is uncommented it shows another copy of the table within the webpage when 'pdfTest' is click, as well as within the pdf preview, but only half of the content.
app.controller('Rollup', function($scope, $rootScope, $http, $uibModal, headersvc, locFiltersvc) {
.....
$scope.genPDF = function(){
html2canvas(document.getElementById("testDiv"), {
onrendered: function (canvas) {
//document.body.appendChild(canvas);
var img = canvas.toDataURL("image/png");
var doc = new jsPDF();
doc.addImage(img, 'JPEG',10,10);
doc.save('test.pdf');
//IE 9-11 WORK AROUND
if (navigator.userAgent.indexOf("MSIE ") > 0 ||
navigator.userAgent.match(/Trident.*rv\:11\./))
{
var blob = canvas.msToBlob();
window.navigator.msSaveBlob(blob,'Test file.png');
}
},
//width: 300,
//height: 300
});
}
});
Of course within the html page where the table is created, I have an id of testDiv within the div to the content I want appearing in the pdf.(route.html)
<div class="row" id="testDiv">
....all the table content
</div>
How can I fit the full content to the pdf preview without it cutting off? Any help is greatly appreciated.
Found a solution where I add parameters to the doc.addImage.
doc.addImage(img, 'JPEG',10,10,190,200);
I am not sure how to make the image 100 % of the pdf page, but with this I can set parameters that work best for the table atleast. Hopefully I can find a better solution, but this works for now.

Random Image Position in programming website?

I want to make it so I have "enemies" spawn in the background (not THE background, just images on top of it) of a particular webpage at random heights and scroll across the screen. Right now I have something like:
<script>
function numberRandomizer(){
var x = Math.floor((Math.random() * 500) + 300); //random number between 300 and 800
return x;
}
</script>
I've tried 2 methods to applying this random variable X to the images that loop by scrolling on screen:
1) Doing what I thought would work and editing each image to get a random value for top and left
<marquee behavior="scroll" direction="left" scrollamount="numberRandomizer()"><img src="/aboutme/enemy.png" width="120" height="80" top="numberRandomizer()" left="numberRandomizer()"/><p></marquee>
2) Even though as far as I know it would make all enemies have the same position, try out CSS styling to make the placement random just to see if it would work:
<style>
img {
top: numberRandomizer();
left: numberRandomizer();
}
</style>
Neither style works in setting a random value for the image location, am I getting a minor thing wrong or going about this completely the wrong way?
As a bonus question: Is it possible to set marquee to go a random direction per image?
You can make the same thing using plain javascript too
html:
<marquee behavior="scroll" direction="left" id="elem">Test</marquee>
<br/>
<button id="butR">Right</button>
<button id="butL">Left</button>
<div class="area">
<div id="enemy"></div>
</div>
Js:
document.getElementById('butR').addEventListener("click", function(){
document.getElementById('elem').setAttribute("direction", "right");
});
document.getElementById('butL').addEventListener("click", function(){
document.getElementById('elem').setAttribute("direction", "left");
});
function numberRandomizer(){
var x = Math.floor((Math.random() * 250) + 50); //random number between 50 and 300
return x;
}
document.getElementById('enemy').style.top = numberRandomizer() + 'px';
document.getElementById('enemy').style.left = numberRandomizer() + 'px';
I've added also a way to change marque direction. Take a look at this fiddle:
https://jsfiddle.net/oyv324z9/
As a couple people said, you can't mix JS and CSS. If you are using jQuery though, this is pretty simple. Basically, you want to use jQuery to add CSS styles to the img. Something like this.
//your trigger here and then..
$( "#your_img_id" ).css( "left", function(index) {
return index * numberRandomizer() ;
});
$( "#your_img_id" ).css( "right", function(index) {
return index * numberRandomizer() ;
});

Fade transition

I am looking to create a photographic website which has a background image that changes every few seconds. I have the images changing by using:
<script type='text/javascript'>
var imageID=0;
function changeimage(every_seconds){
//change the image
if(!imageID){
document.getElementById("myimage").src="John%20Gallacher%20Photography/images/composite/Composite%201.jpg";
imageID++;
}
else{if(imageID==1){
document.getElementById("myimage").src="John%20Gallacher%20Photography/images/composite/Composite%202.jpg";
imageID++;
}
else{if(imageID==2){
document.getElementById("myimage").src="John%20Gallacher%20Photography/images/composite/Composite%203.jpg";
imageID=0;
}
}
}
//call same function again for x of seconds
setTimeout("changeimage("+every_seconds+")",((every_seconds)*5000));
}
</script>
</head>
<body onload='changeimage(2)'>
<div>
<img id="myimage" src="John%20Gallacher%20Photography/images/composite/Composite%201.jpg"/>
</div>
Is it possible to make the images fade in and then out again, and if so what would be the easiest way to do this. I have a basic understanding of html and css, my javascript is very basic. Any help would be great thanks
What is the support list? If you're not worried about older IE, then you can go with CSS Transitions for the transition and change the state with js
http://jsfiddle.net/Bushwazi/MYKFT/
#myimage {
-webkit-transition:all 1s linear 0s;
-moz-transition:all 1s linear 0s;
-o-transition:all 1s linear 0s;
transition:all 1s linear 0s;
-webkit-transform: translate3d(0,0,0); /* Fixes trails in Chrome */
}
And then just use js to change the opacity, then image, the opacity...
var imageID = 0,
ti = document.getElementById("myimage");;
var changeImage = function(t){
// change the opacity of the image to 0, let the css control the animation
ti.style.opacity = "0.0";
ti.style.filter = 'alpha(opacity=00)'; // IE fallback
// after 1 second (the animation), change the image
setTimeout(function(){
//change the image
switch(imageID){
case 0:
ti.src="https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcTM7c8EFwQ_PseqOEblAtm9qXali9kzvBKsmrGDECLYu1HJP3EO";
break;
case 1:
ti.src="https://si0.twimg.com/profile_images/2317326635/3kglmsqti3msjlb1nr60.png";
break;
case 2:
// return to the original image
ti.src="http://upload.wikimedia.org/wikipedia/en/c/cc/FPO_mark3.jpg";
break;
default:
// do nothing
}
if(imageID == 2){
imageID = 0;
} else {
imageID++;
}
// change the opacity of the image to 0, let the css control the animation
ti.style.opacity = "1.0";
ti.style.filter = 'alpha(opacity=100)'; // IE fallback
},1000);
} // close changeimage
//call same function again for x of seconds
window.setInterval(changeImage, 5000);
You may use jQuery. This has a number of transitions including fadeIn() and fadeOut().
Apply those functions to your images like this:
$("#image_id").fadeIn(); $("#image_id").fadeOut();
But firstly in your head you need to include jQuery. You can do that like this:
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
The #image_id is the id= of the <img> in your HTML Markup.
You can use a simple plugin for that, like jQuery Cycle. The code should look like this:
<head>
...
<script src="js/jquery-1.10.1.min.js"></script>
<script src="js/jquery.cycle.lite.js"></script>
...
</head>
...
<div class="fader">
<img src="image1.jpg" width="100px" height="100px">
<img src="image2.jpg" width="100px" height="100px">
<img src="image3.jpg" width="100px" height="100px">
</div>
...
<script>
$('.fader').cycle();
</script>
</body>
Where you shoud replace '/js' with the path to that files (that you should download).
I think a plugin is a lot of overhead for something that you can do with a little code.
I set up a quick example for you:
http://jsfiddle.net/Pevara/XcBTx/1/
A few remarks:
- I chose to work with background images, as I believe a background is what you are after, and you would not want the picture to show up on print. You could argue that for a photography website the background image is actual content, but changing the code to work with images in stead should be easy.
- Note that I use 2 div's for the images, so I can fade one in and one out. Perhaps it would be better to add the second one with javascript to avoid unnessacary markup. The first div I would keep, cause you want users without javascript to see at least one photo. You could consider setting it on the body, but again, I leave that up to you.
- It will be probably nessacary to preload the images, and wait for them to be loaded before you start the slideshow. Should not be to hard, plenty of information out there.
And the javascript (to be put in the $(window).load handler):
// the list of background images
var myImages = ['http://placekitten.com/900/400','http://placekitten.com/550/600'];
// the transition speed
var fadeSpeed = 500;
// the time between transitions
var playSpeed = 2000;
function fadeToNextImage() {
// -- prepare some vars
// the image wrappers
var $bg1 = $('#bg1');
var $bg2 = $('#bg2');
// the index of the next image in our array
var nextNr = parseInt($bg1.data('number')) + 1;
// if the index is larger then the number of images,
// we want the first image
if (nextNr > myImages.length - 1) { nextNr = 0; }
// the path to the next image
var nextImg = 'url(' + myImages[nextNr] + ')';
// set the image as background on bg2
$bg2.css('background-image', nextImg);
// fade out bg1
$bg1.fadeOut(fadeSpeed);
// fade in bg2
$bg2.fadeIn(fadeSpeed, function() {
// when the cross fade is ready
// set the image as background on bg1
$bg1.css('background-image', nextImg);
// update the number attribute
$bg1.data('number', nextNr);
// show bg1 (which now contains the same image as bg2)
$bg1.show();
// hide bg2 (to prepare it for the next slide)
$bg2.hide();
});
}
// start the slideshow
var interval = window.setInterval(function() {fadeToNextImage();}, playSpeed + fadeSpeed);
I put plenty of comments in there, but feel free to ask!

AngularJS ng-href and svg xlink

I'd like some input on using xml namespaced attributes with angular.
The problem is angular comes with a couple of directives to handle writing attributes such as href and src when angular has parsed the expresssions (otherwise the browser will try to load {{mymodel.myimage}} as a url)
https://github.com/angular/angular.js/blob/master/src/ng/directive/booleanAttrs.js#L329
The problem I'm facing is that I'm using angular to output svg together with D3 and since angular doesn't have a way to output xlink:href I was stuck.
I created a custom directive that outputs xlink:href
app.directive('ngXlinkHref', function () {
return {
priority: 99,
restrict: 'A',
link: function (scope, element, attr) {
var attrName = 'xlink:href';
attr.$observe('ngXlinkHref', function (value) {
if (!value)
return;
attr.$set(attrName, value);
});
}
};
});
Full demo: http://plnkr.co/edit/cMhGRh
But it seems that if I don't manually add xlink:href to the element, the svg image will not render.
Any suggestions on how to best handle xml namespaces / svg together with angular would be greatly appreciated.
You can use ng-attr-<some attribute>
ng-attr-xlink:href="{{xxx}}" works for me.
Note that you also need an empty xlink:href="" as initial value. – Derek Hsu
If, like me, you're looking for a way to add images to svg, you can do so adding:
xlink:href="" ng-href="{{ foo }}"
Example:
http://jsbin.com/sigoleya/1/edit?html,js,output
Where I found the solution:
https://github.com/angular/angular.js/issues/7697
I ran into a similar problem when trying to output a value for xlink:href that's tied to the model. Based on the user's chosen <option> in a <select> control, I was trying to show a dynamic SVG icon via the xlink:href attribute of the <use> element.
I found a thread about this in the GitHub Issues for AngularJS. Based on the discussion there, it appears that because a viable workaround exists, they've effectively tabled a fix by moving it to the Backlog milestone.
What ultimately worked for me was inspired by this JSBin:
http://jsbin.com/sigoleya/1/edit?html,js,output
Here's the code I used in my template:
<svg class="icon" data-ng-class="category.iconName">
<use xlink:href="" data-ng-href="{{'#' + category.iconName}}">
</svg>
Given a category.iconName of icon-music, for example, Angular sets the xlink:href dynamically to #icon-music, which references the <svg id="icon-music"> element further up on the same page.
As others have noted, what's key is setting a blank xlink:href="" attribute on the element where you call the ngHref directive. Attribute order does not seem to matter. Using ng-attr-xlink:href="{{xxx}}" (as mentioned in Derek Hsu's answer) did not work for me.
All of this assumes Angular 1.3.36.
I solved the same problem with the following modules:
Module for SVGs:
var app = angular.module('Svgs', []);
angular.forEach([
{ ngAttrName: 'ngXlinkHref', attrName: 'xlink:href' },
{ ngAttrName: 'ngWidth', attrName: 'width' },
{ ngAttrName: 'ngHeight', attrName: 'height' }
], function (pair) {
var ngAttrName = pair.ngAttrName;
var attrName = pair.attrName;
app.directive(ngAttrName, function (IeHelperSrv) {
return {
priority: 99,
link: function (scope, element, attrs) {
attrs.$observe(ngAttrName, function (value) {
if (!value) return;
attrs.$set(attrName, value);
if (IeHelperSrv.isIE) element.prop(attrName, value);
});
}
};
});
});
Module for IE detection:
angular.module('IeHelper', []).factory('IeHelperSrv', function () {
return {
isIE: checkForIE.isIE,
}
});
var checkForIE = {
init: function () {
this.isIE = (navigator.userAgent.indexOf('MSIE') != -1);
}
};
checkForIE.init();
HTML:
<!-- image has initial fake source, width and height to force it to render -->
<image xlink:href="~/Content/Empty.png" width="1" height="1"
ng-xlink-href="{{item.imageSrc}}"
ng-width="{{item.width}}" ng-height="{{item.height}}"
ng-cloak
/>
For anyone else having this problem due to Angular/Angular UI Router in HTML5 mode, I came up with a straightforward fix to enable svg sprite icons to work with their xlink:href attribute and the tag.
Gist is here: https://gist.github.com/planetflash/4d9d66e924aae95f7618c03f2aabd4a3
app.run(['$rootScope', '$window', function($rootScope, $window){
$rootScope.$on('$locationChangeSuccess', function(event){
$rootScope.absurl = $window.location.href;
});
<svg><use xlink:href="{{absurl+'#svgvID'}}"></use></svg>
I ran into this problem where I was using Ajax to load the svg spritesheet onto the page. If I had a on the page before the spritesheet was loaded, it would fail and would not resolve once the spritesheet was avaialble. Any added to the dom after the spritesheet was loaded were fine. I had to delay putting the items in the dom until after the spritesheet finished loading.
This only affected IOS. All other browsers didn't care about the order.
This took me more time than I would've wanted. Around 20-30 minutes.
If I understand correctly, any failed loading on image element will render that element useless in the future. I believe it's something similiar #GeekyMonkey is saying. If angular binding system has set xlink:href initially to null, Image element wont work anymore, even if we have valid value in the future.
Here is solution, notice how I have wrapped image element inside g element, using ng-if directive. That makes sure we will bind against image only when a correct value is available.
<g ng-if="vm.svgMap.background != null">
<image
ng-attr-xlink:href="{{vm.svgMap.background.image | trusted}}"
ng-attr-width="{{vm.svgMap.background.width}}"
ng-attr-height="{{vm.svgMap.background.width}}"
xlink:href=""
width="1"
height="1"
x="0"
y="0"></image>
</g>
As others said, the order of attributes are important as well. To ensure that angularJS allows us to bind image element, we'll also have to trust that resource, I've done it through filter (it's the one in xlink:href attribute):
(function() {
'use strict';
angular.module('myTool').filter('trusted', TrustedFilter);
function TrustedFilter($sce) {
return function(url) {
return $sce.trustAsResourceUrl(url);
};
};
}());