Raphael JS paper.set and multiple access - arrays

I try to create a set of Raphael objects, and animate them when window (for example) is clicked.
So this works: http://jsfiddle.net/6YdrG/2/
$(function() {
(function () {
var R = Raphael($('#svg')[0]);
var i, circles = circlenumber = R.set();
var v = [{offset: 0, circleVal: '+ 29 %'}, {offset: 120, circleVal: '+ 90 %'}, {offset: 240, circleVal: '+ 107 %'}, {offset: 360, circleVal: '+ 20 %'}];
for (i = 0; i <= 3; i++) {
circles[i] = R.circle(29+v[i].offset, 29, 10).attr({fill: '#000', stroke: 'none'});
//circlenumber[i] = R.text(29+v[i].offset, 29, v[i].circleVal).attr({font: '12px JauresSemibold, serif', fill: '#fff'});
};
$(window).click(function() {
console.log('click');
for (i = 0; i <= 3; i++) {
circles[i].animate(Raphael.animation({r: 28}, 800, 'easeInOut').delay(100*(i)));
};
});
})();
});
But if you remove "//" to add the circlenumber[i] elements, it doesn't works anymore…
Ideas? Thanks!

I think your problem is the way you define i
Check this http://jsfiddle.net/6YdrG/5/
You had i initialised as R.Set().

Related

Filling a chart with a color above a specific Y value

I've been trying to fill a chart with color above certain Y value and I can't do it.
What I tried to do is writing a condition that if the value is >3.5 that area of the chart will be filled with a different color.
splineSeries.fill(function() {
if (this.value > 3.5)
return '#d3f335 0.4'
else
return '#cdf0a7 0.6'})
However, this doesn't work for me as it fills the whole area of the chart which values are >3.5 and not only the area that it's above the line.
This is how that chunk of code is working in my chart.1
If you know how this can be solved I would really appreciate if you help me :)
Thanks!!
It does not seem AnyChart supports this kind of filling out of the box. You can however get creative with gradients:
var cmin = chart.getStat("yScalesMin");
var cmax = splineSeries.getStat('seriesMax');
var cutoff = 3.5;
splineSeries.fill({
angle: 90,
keys: [{
color: '#cdf0a7',
opacity: 0.6,
offset: (cutoff-cmin) / (cmax-cmin)
}, {
color: '#d3f335',
opacity: 0.4,
offset: (cutoff-cmin) / (cmax-cmin)
}],
thickness: 3
});
Here's a working example:
chart = anychart.area();
var series = chart.area(generateRandomData());
var cmin = chart.getStat("yScalesMin");
var cmax = series.getStat('seriesMax');
var cutoff = 3.5;
series.fill({
angle: 90,
keys: [{
color: '#cdf0a7',
opacity: 0.6,
offset: (cutoff-cmin) / (cmax-cmin)
}, {
color: '#d3f335',
opacity: 0.4,
offset: (cutoff-cmin) / (cmax-cmin)
}],
thickness: 3
});
chart.container("chart");
chart.draw();
function generateRandomData() {
var data = [];
for (let i=0; i<16; i++) {
data.push({x:i, value:Math.random() * 7.5});
}
return data;
}
#chart {
height: 400px;
}
<script src="https://cdn.anychart.com/releases/8.11.0/js/anychart-core.min.js"></script>
<script src="https://cdn.anychart.com/releases/8.11.0/js/anychart-cartesian.min.js"></script>
<div id="chart"></div>
This should also work with charts with yScalesMin > 0

do not show 0 value on google line chart

var data = google.visualization.arrayToDataTable([
['Year', 'Massachusetts', 'National'],
['2010', 88, 76],
['2011', 0, 82],
['2012', 96, 86],
['2013', 100, 91],
['2014', 0, 94],
['2015', -1, 98],
['2016', 100, 99],
['2017', 124, 100],
['2018', 125, 102]
]);
This is the data I am using to create a line chart, I do not want to show 0's and negative values on the chart. I just want to skip these values.
my current chart looks like this
Expected chart is like this
we can use a data view with calculated columns,
to replace values less than or equal to zero with null
var view = new google.visualization.DataView(data);
var viewColumns = [0];
for (var i = 1; i < data.getNumberOfColumns(); i++) {
addViewColumn(i);
}
view.setColumns(viewColumns);
function addViewColumn(columnIndex) {
viewColumns.push({
calc: function (dt, row) {
var valNew = null;
var valOrig = dt.getValue(row, columnIndex);
if (valOrig > 0) {
valNew = valOrig;
}
return valNew;
},
label: data.getColumnLabel(columnIndex),
type: data.getColumnType(columnIndex)
});
}
then use the following configuration option, which skips null values
interpolateNulls: true
see following working snippet...
google.charts.load('current', {
packages: ['corechart']
}).then(function () {
var data = google.visualization.arrayToDataTable([
['Year', 'Massachusetts', 'National'],
['2010', 88, 76],
['2011', 0, 82],
['2012', 96, 86],
['2013', 100, 91],
['2014', 0, 94],
['2015', -1, 98],
['2016', 100, 99],
['2017', 124, 100],
['2018', 125, 102]
]);
var view = new google.visualization.DataView(data);
var viewColumns = [0];
for (var i = 1; i < data.getNumberOfColumns(); i++) {
addViewColumn(i);
}
view.setColumns(viewColumns);
function addViewColumn(columnIndex) {
viewColumns.push({
calc: function (dt, row) {
var valNew = null;
var valOrig = dt.getValue(row, columnIndex);
if (valOrig > 0) {
valNew = valOrig;
}
return valNew;
},
label: data.getColumnLabel(columnIndex),
type: data.getColumnType(columnIndex)
});
}
var options = {
title: 'Average Home Insurance Premium',
interpolateNulls: true
};
var chart = new google.visualization.LineChart(document.getElementById('chart'));
chart.draw(view, options);
});
<script src="https://www.gstatic.com/charts/loader.js"></script>
<div id="chart"></div>

Load from JSON with dynamic patterns, patternSourceCanvas is not defined error return by the serialize JSON data

I am trying to save Fabric.js canvas and reload it using loadFromJson. But I am getting error patternSourceCanvas is not defined. I thought I should make it global so I removed var.
How to set the global variable in Fabric JS and use var patternSourceCanvas?
When I use the code below, then everything is working fine and the JSON is loaded easily.
var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg
fabric.util.loadImage(t, function(t) {
var svg_width = i.width;
console.log('svg widh' + i.width + 'svg height' + i.height);
console.log('img width t'+ t.width + ' img height' + t.height);
if(svg_width >= 300){
if (i.isSameColor && i.isSameColor() || !i.paths) {
i.setPatternFill({
source: t, repeat: 'repeat', offsetX:200 , offsetY : -110 // working
}), e.fabric.renderAll();
console.log('in if image 300 up ', t);
} else if (i.paths){
for (var r = 0; r < i.paths.length; r++)
i.paths[r].setPatternFill({
source: t, repeat: 'repeat' , offsetX: -100 , offsetY:-110
}), e.fabric.renderAll();
console.log('in image elseeee 300 up ', t);
}
}
})
But when I fill some other new shape with the new patternSourceCanvas variable then it's not working. Kindly help me with dynamic patterns.
var t = https://image.freepik.com/free-photo/roof-texture_21206171.jpg
fabric.Image.fromURL(t, function (img) {
img.scaleToHeight(200);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.renderAll();
var pattern = new fabric.Pattern({
source: function() {
patternSourceCanvas.setDimensions({
width: img.getScaledWidth() ,
height: img.getScaledHeight()
});
patternSourceCanvas.renderAll();
return patternSourceCanvas.getElement();
},
repeat: r
});
console.log('pattern', pattern);
//p.set('fill', pattern);
canvas.renderAll();
if (i.isSameColor && i.isSameColor() || !i.paths) {
i.setPatternFill(pattern);
} else if(i.paths) {
for (var r = 0; r < i.paths.length; r++) {
i.paths[r].setPatternFill(pattern);
}
}
e.fabric.renderAll();
});
You need to put patternSourceCanvas to global scope/ scope where loadFromJSON can access patternSourceCanvas. Else you can use cors enabled image directly.
DEMO
var imageUrl = 'https://upload.wikimedia.org/wikipedia/commons/2/22/Wikimapia_logotype.svg';
var canvas = new fabric.Canvas('canvas');
var rect = new fabric.Rect({
width: 200,
height: 200,
strokeWidth: 2,
stroke: '#000'
})
canvas.add(rect);
fabric.Image.fromURL(imageUrl, function(img) {
img.scaleToHeight(200);
var patternSourceCanvas = new fabric.StaticCanvas();
patternSourceCanvas.add(img);
patternSourceCanvas.setDimensions({
width: img.getScaledWidth(),
height: img.getScaledHeight()
});
patternSourceCanvas.renderAll();
var pattern = new fabric.Pattern({
source: patternSourceCanvas.getElement()
},
function(patternObj) {
rect.fill = patternObj;
rect.dirty = true;
canvas.renderAll();
});
}, {
crossOrigin: 'annonymous'
});
function loadfromjson() {
var json = canvas.toJSON();
canvas.clear();
setTimeout(function() {
canvas.loadFromJSON(json, canvas.renderAll.bind(canvas));
}, 1000)
}
canvas{
border:2px solid #000;
}
<canvas id="canvas" width="300" height="300"></canvas><br>
<button onclick="loadfromjson()">loadfromjson </button>
<script src='https://rawgit.com/kangax/fabric.js/master/dist/fabric.js'></script>

Angular ui-grid auto height not working

I am using angular ui-grid for show records. I have a product which has only 7 records, and another product which has 200 records. By default max row are selected to 20 when records are greater than 20, when records are less than 20 grid will auto resize depending on records count.
Problem is that; when I load 7 records in grid, the height of grid is according to 7 records, keeping there without refreshing page, when I type another records which has 200 entries in search box and submit, it assigns all records to grid but the size of grid remains the same as of 7 records.
I need to make grid auto resizeable according to records, keeping 20 records in page in records are more than or equal to 20.
here is some code from grid directive;
scope.configuration = {
data: scope.data,
exporterCsvFilename: 'testfile' + '.csv',
exporterMenuPdf: true,
enableSelectAll: true,
// enablePaging: true,
enablePaginationControls: true,
paginationPageSizes: [10, 20, 30, 40, 50, 100],
enableGridMenu: true,
enableFiltering: true,
paginationPageSize: (scope.largeGrid) ? 20 : 10,
enableHorizontalScrollbar: 1,
enableVerticalScrollbar: 0,
heights
scope.getGridHeight = function (data) {
var length = (scope.configuration.paginationPageSize > data.length) ? data.length : scope.configuration.paginationPageSize;
var rowHeight = (scope.autoHeightColumn) ? scope.getAutoHeight(data, scope.autoHeightColumn) : 30; // your row height
var headerHeight = 50; // your header height
var filterHeight = 62; // your filter height
if (scope.autoHeightColumn) {
return rowHeight + headerHeight + filterHeight + 'px';
}
return length * rowHeight + headerHeight + filterHeight + 'px';
};
scope.$watch('configuration.paginationPageSize', function () {
scope.gridHeight = scope.getGridHeight(scope.data);
//kind of hack: as minification does not setting interpolated variable.
$('#grid').css('height', scope.gridHeight);
});
scope.getAutoHeight = function (data, colum) {
//Todo: Get pagination and data height separately
var totalHeight = 0;
for (var i = 0; i < data.length; i++) {
var columnHeight = data[i][colum].length;
if (columnHeight) {
columnHeight = (columnHeight / 12) * 23;
} else {
columnHeight = 23;
}
totalHeight += columnHeight;
}
return totalHeight;
};
we can achieve ui-grid auto height using some css overrides.
.ui-grid-viewport
{
overflow-x: hidden !important;
overflow-y: auto !important;
}
.ui-grid, .ui-grid-viewport
{
height: auto !important;
}
.ui-grid-viewport, .ui-grid-canvas
{
height: auto !important;
}
.ui-grid-row, .ui-grid-cell
{
height: auto !important;
}
.ui-grid-row div[role=row]
{
display: flex;
align-content: stretch;
}
.ui-grid, .ui-grid-viewport
{
height: auto !important;
}
.ui-grid-viewport, .ui-grid-canvas
{
height: auto !important;
}

Dynamically change zoom

I need to change zoom of Google Maps. Code:
function _initMap(vm) {
vm.windowOptions = {
show: false
};
var latSum = 0;
var longSum = 0;
for (var i = 0, length = vm.markers.length; i < length; i++) {
//calculate center of map (1st part)
latSum += vm.markers[i].coords.latitude;
longSum += vm.markers[i].coords.longitude;
//assign an icon
vm.markers[i].iconUrl = getIconUrl(vm.markers[i].deviceType);
}
var centeredLatitude = latSum / vm.markers.length;
var centeredLongitude = longSum / vm.markers.length;
vm.control = {};
vm.map = {
center: setCenterMap(),
options: getMapOptions(),
zoom: setMapZoom(),
events: {
click: function (mapModel, eventName, originalEventArgs) {
var e = originalEventArgs[0];
$log.log('gz', e.latLng.lat() + ' ' + e.latLng.lng());
console.log('xxx', mapModel);
}
},
show: true,
refresh: function (a, b, c, d) {
vm.map.control.refresh();
}
};
vm.clusterOptions = {
minimumClusterSize: 2,
zoomOnClick: true,
styles: [{
url: 'assets/images/markers/m1.png',
width: 53,
height: 53,
textColor: 'white',
textSize: 17,
fontFamily: 'Open Sans'
}],
averageCenter: true,
clusterClass: 'cluster-icon'
};
vm.window = {
location: undefined,
templateUrl: 'app/components/maps/maps.info.template.html',
show: false,
options: getMapWindowOptions()
};
vm.clickMarker = function (marker, event, object) {
vm.window.show = false;
vm.window.details = object.details;
vm.window.location = object.coords;
vm.window.show = true;
vm.sendChoosenDeviceToController(object);
angular.element('#right-menu').focus();
};
vm.closeClick = function () {
vm.window.show = false;
}
}
but the code:
center: setCenterMap()
zoom: setMapZoom()
when I call the methods center and zoom does not change center and zoom. How to update center and zoom dynamically ? The methods are properly exectued during initiation of map but after initialization does not want to change.
The solution was just simply:
scope.map.center = {
'latitude': scope.markers[i].coords.latitude,
'longitude': scope.markers[i].coords.longitude
};
GoogleMaps knows about that change and works nice.

Resources