Scale entire draw container content - extjs

See the fiddle for the test code: https://fiddle.sencha.com/#fiddle/1jro
or code below:
Ext.application({
name : 'Fiddle',
launch : function() {
var container = new Ext.draw.Container({
renderTo: Ext.getBody(),
width: 400,
height: 300
});
var surf = container.getSurface();
var s1 = surf.add({
type: 'rect',
x: 50, y: 10, width: 300, height: 80, radius: 50,
fillStyle: '#ff0000', strokeStyle: 'black'
});
var s2 = surf.add({
type: 'path', path: 'M 50, 110 l 100 80 l 100 -80 l 100 80',
fillStyle: '#00ff00', strokeStyle: 'black'
});
var s3 = surf.add({
type: 'rect',
x: 50, y: 210, width: 300, height: 80, radius: 50,
fillStyle: '#0000ff', strokeStyle: 'black'
});
container.renderFrame();
// Resize (halve x and y)
setTimeout(function() {
container.setSize(200, 150);
s1.setAttributes({scalingX: 0.5, scalingY: 0.5});
s2.setAttributes({scalingX: 0.5, scalingY: 0.5});
s3.setAttributes({scalingX: 0.5, scalingY: 0.5});
container.renderFrame();
}, 5000);
}
});
What I would like to do is to be able to scale the entire draw container with all sprites moved and scaled appropriately. When I halve the container, the whole image should just get smaller. Can this be done is some way? My current implementaion is wrong as only scaling is applied and the positions are invalid.

The answer is simple in the end. Just use scalingCenter(X and Y):
s1.setAttributes({scalingX: 0.5, scalingY: 0.5, scalingCenterX: 0, scalingCenterY: 0});
s2.setAttributes({scalingX: 0.5, scalingY: 0.5, scalingCenterX: 0, scalingCenterY: 0});
s3.setAttributes({scalingX: 0.5, scalingY: 0.5, scalingCenterX: 0, scalingCenterY: 0});

Related

Multiple Gauge Chart

Is it possible to Draw this type of gauges in the left and right of the circle using Highcharts?
Basically left side gauge is representing the shorts' %age at left, the right side gauge is representing the shorts' %age at right, and the center is one simple round circle with the %age of center shots.
Series variable pie it's looks fit better for this case.
Tooltip we built setting useHTML:true, circle at the center we rendered by SVG renderer.
Highcharts.chart('container', {
chart: {
events: {
render() {
const chart = this;
if (!chart.customCenterCircle) {
chart.customCenterCircle = chart.renderer.circle(
chart.plotLeft + chart.plotSizeX / 2,
chart.plotTop + chart.plotSizeY / 2,
0
).add().toFront();
}
if (!chart.customCenterText) {
chart.customCenterText = chart.renderer.text('50%', 0, 0).css({
fontSize: '24px',
color: '#d4d4d4'
}).add().toFront();
}
chart.customCenterCircle.animate({
x: chart.plotLeft + chart.plotSizeX / 2,
y: chart.plotTop + chart.plotSizeY / 2,
r: chart.series[0].center[3] / 2,
fill: 'rgba(31, 112, 31, 0.5)',
stroke: 'rgba(154, 214, 154, 1)',
'stroke-width': 4
});
chart.customCenterText.attr({
x: chart.plotLeft + chart.plotSizeX / 2 -
chart.customCenterText.getBBox().width / 2,
y: chart.plotTop + chart.plotSizeY / 2 -
chart.customCenterText.getBBox().y -
chart.customCenterText.getBBox().height / 2
});
}
}
},
tooltip: {
backgroundColor: '#ffffff',
borderWidth: 0,
useHTML: true,
formatter: function() {
return `<p><h1 style="color:${this.color};">${this.y}</h1></br>${this.key}</p>`
}
},
series: [{
type: 'variablepie',
minPointSize: 0,
innerSize: '30%',
startAngle: 30,
dataLabels: {
enabled: false
},
borderWidth: 3,
zMin: 0,
data: [{
y: 80,
z: 100,
name: 'other',
color: 'black'
}, {
y: 30,
z: 100,
name: 'missed right',
color: 'red'
}, {
y: 50,
z: 0
}, {
y: 25,
z: 80,
name: 'missed right',
color: 'red'
}, {
y: 75,
z: 80,
name: 'other',
color: 'black'
}, {
y: 60,
z: 0,
name: 'other',
}]
}]
});
Live demo:
https://jsfiddle.net/BlackLabel/sc9vwzjt/2/
API References:
https://www.highcharts.com/docs/chart-and-series-types/variable-radius-pie-chart
https://api.highcharts.com/highcharts/series.variablepie
https://api.highcharts.com/class-reference/Highcharts.SVGRenderer

Individual shape and position of annotations in highcharts

I have figured out how to set the size for an annotation individually:
labels: [
{
point: {
x: chart.xAxis[0].max - 0.1,
y: 50,
xAxis: 0,
yAxis: 0
},
height: 100,
shape: "rect",
text: "test",
verticalAlign: "bottom"
}
]
I would like it to position between 50 and 150. How can I achieve that?
And additionally, I would like the text to be aligned in the center of the box?!
You can calculate the height by using toPixels method. You have to also take a padding into account. To center the text you can use asynchronous function, because annotations do not exist in load event yet.
chart: {
events: {
load: function() {
const chart = this;
const height =
chart.yAxis[0].toPixels(50) - chart.yAxis[0].toPixels(150);
chart.addAnnotation({
labels: [
{
point: {
x: chart.xAxis[0].max - 0.1,
y: 150,
xAxis: 0,
yAxis: 0
},
y: 0,
padding: 0,
height: height,
shape: "rect",
text: "test",
verticalAlign: "top"
}
]
});
}
}
}
Live demo: https://codesandbox.io/s/qqqkx2zr49
API: https://api.highcharts.com/class-reference/Highcharts.Axis#toPixels

Multiple polygons in angular leaflet "paths"

I am trying to display multiple paths in my OSM maps using angular leaflet. Paths types like multiple circle and polygons.
For circle, the below code:
angular.forEach($scope.alertcircles, function(obj, key){
var arraylen = obj.g_pos_circle.coordinates[0].length;
console.log(obj.id);
$scope.paths['circle' + obj.id] = {
circle: {
color: '#FF0000',
opacity: 0.5,
stroke: false,
fillColor: '#ff69b4',
fillOpacity: 0.5,
weight: 8,
radius: 6,
latlngs: [],
type: 'circle',
clickable: true,
heading: 240
}
};
for(i=0; i<obj.g_pos_circle.coordinates[0].length;i++){
var coord = obj.g_pos_circle.coordinates[0][i];
angular.extend($scope.paths ['circle' + obj.id] .circle.latlngs.push({
lat: parseFloat(coord[1]),
lng: parseFloat(coord[0])
}))
}
$scope.paths['circle' + obj.id].circle.radius = obj.g_pos_radius
});
For polygon
angular.forEach($scope.alertareas, function(obj, key){
var arraylen = obj.g_pos_poly.coordinates[0].length;
console.log(obj.id);
$scope.paths['area' + obj.id] = {
area: {
color: '#FF0000',
opacity: 0.5,
stroke: false,
fillColor: '#ff69b4',
fillOpacity: 0.5,
weight: 0,
latlngs: [],
type: 'polygon',
clickable: true,
heading: 240
}
};
for(i=0; i<obj.g_pos_poly.coordinates[0].length-1; i++){
var coord = obj.g_pos_poly.coordinates[0][i];
angular.extend($scope.paths ['area' + obj.id ] .area.latlngs.push({
lat: parseFloat(coord[1]),
lng: parseFloat(coord[0])
}))
}
});
I am not able to see any shapes in my map. I previously had a setup like below but the problem is all the shapes are connected as there no differentiation among different shapes
$scope.paths = {
area: {
color: '#FF0000',
opacity: 0.5,
stroke: false,
fillColor: '#ff69b4',
fillOpacity: 0.5,
weight: 0,
latlngs: [],
type: 'polygon',
clickable: true,
heading: 240
},
circle: {
color: '#FF0000',
opacity: 0.5,
stroke: false,
fillColor: '#ff69b4',
fillOpacity: 0.5,
weight: 8,
radius: 6,
latlngs: [],
type: 'circle',
clickable: true,
heading: 240
}
};
What approach do I have to follow to show individual shapes correctly. Any help is greatly appreciated.
I had the same problem, and the reason was in included css with style
svg{
width: 100%;
height: 100%;
}
Correction
.angular-leaflet-map svg{
width: initial;
height: initial;
}
resolve the problem

how to convert text to image in kinetic js version 5.1.0

My following code work fine with kineticjs version 4.4.3 but give error with kineticjs version 5.1.0 (as shown in screen shot)
Code is:
var simpleText = new Kinetic.Text({
x: 50,
y: 50,
text: 'TESTING',
fontSize: 16,
fill: "white"
});
simpleText.toImage({
width:50,
height:50,
x : 50,
y : 50,
callback: function(img){
var yodaImg = new Kinetic.Image({
image: img,
x: 0,
y: 0,
width: 50,
height: 50,
name: 'image'
});
console.log(yodaImg.src);
}
});
For some reasons I have to use this latest version.
Any solution?
Thanks in advance
var textOnCanvas = new Kinetic.Text({
x: 0,
y: 0,
text: fullText,
fontFamily: "Arial",
fontSize: 22,
fill: '#000000',
align: 'left',
padding: 5,
width: 1024
});
layer.add(textOnCanvas);
layer.draw();
var textImgSrc = textOnCanvas.toDataURL(); // base64 image of text
var textImgObj = new Image();
textImgObj.src = textImgSrc;
var kineticIMG = new Kinetic.Image({
image: textImgObj,
x: 0,
y: 0,
});
src will be in base64 string. Then you can apply this image to the Kinetic.Image() object.

Custom component not displaying on an Ext.panel.Panel

I have extended a component and I can't get it to render to a panel. Seems like I am missing something pretty basic since the debugger in Chrome actually shows that the panel has the data, it just isn't showing up.
Here is the fiddle and here are parts of the code:
Custom Component:
Ext.define('StoplightControl', {
extend: 'Ext.draw.Component',
alias: 'widget.Stoplight',
constructor: function (config) {
this.initConfig(config);
this.callParent(arguments);
},
initComponent: function () {
var kpiData; // = Ext.data.StoreManager.get('KPIStore').getById(this.model.get('KPI_ID'));
if (typeof (kpiData) === 'undefined' || kpiData == null) {
kpiData = Ext.create('KPIModel', {
ControlBackground: '#000000',
Caution_label: 'On',
Good_label: 'Ahead',
Poor_label: 'Behind',
Good_color: '#00FF00',
Poor_color: '#ff0000',
Caution_color: '#550000',
Header: 'Test'
});
}
this.setGradients(kpiData.get('ControlBackground'));
this.drawItems(this.model, kpiData);
},
setGradients: function (controlColor) {
this.gradients = [{
id: 'middleGradient',
angle: 180,
stops: {
0: {
color: controlColor,
opacity: 1
},
50: {
color: controlColor,
opacity: .6
},
100: {
color: controlColor,
opacity: 1
}
}
}, {
id: 'lightGradient1',
angle: -90,
stops: {
0: {
color: '#ffffff',
opacity: 0.01
},
100: {
color: '#ffffff',
opacity: .8
}
}
}]
},
drawItems: function (model, kpiData) {
var cautionValueX = -22.5 * (model.get('cautionValue').toString().length) + 227.5,
goodValueX = -22.5 * (model.get('goodValue').toString().length) + 227.5,
poorValueX = -22.5 * (model.get('poorValue').toString().length) + 227.5,
maxLineLength = 15,
changeOfY = -50,
cautionLabel = linebreaks(kpiData.get('Caution_label'), maxLineLength),
goodLabel = linebreaks(kpiData.get('Good_label'), maxLineLength),
poorLabel = linebreaks(kpiData.get('Poor_label'), maxLineLength),
cautionChangeY = (cautionLabel.split("\n").length - 1) * changeOfY,
goodChangeY = (goodLabel.split("\n").length - 1) * changeOfY,
poorChangeY = (poorLabel.split("\n").length - 1) * changeOfY,
headerFontSize = '100px arial,sans-serif',
textFontSize = '80px arial,sans-serif';
var drawItems = [{
type: 'rect',
x: 1.6620979,
y: 52.362183,
radius: 90,
width: 448.10959,
height: 1000,
fill: 'url(#middleGradient)',
stroke: 'none'
}, {
type: "circle",
radius: 140,
x: 224,
y: 896,
stroke: "#000000",
'stroke-width': 1,
fill: kpiData.get('Good_color')
}, {
type: "circle",
x: 224,
y: 214,
radius: 140,
stroke: "#000000",
'stroke-width': 1,
fill: kpiData.get('Poor_color')
}, {
type: "circle",
x: 224,
y: 555,
radius: 140,
stroke: "#000000",
'stroke-width': 1,
fill: kpiData.get('Caution_color')
}, {
type: "text",
id: "svg-stoplight-poorValue",
text: model.get('poorValue'),
x: poorValueX,
y: 220,
fill: "Black",
font: textFontSize
}, {
type: "text",
id: "svg-stoplight-cautionValue",
text: model.get('cautionValue'),
x: cautionValueX,
y: 560,
fill: "Black",
font: textFontSize
}, {
type: "text",
id: "svg-stoplight-goodValue",
text: model.get('goodValue'),
x: goodValueX,
y: 900,
fill: "Black",
font: textFontSize
}, {
type: "text",
id: "svg-stoplight-poorLabel",
text: poorLabel,
x: 500,
y: 220 + poorChangeY,
fill: "Black",
font: textFontSize
}, {
type: "text",
id: "svg-stoplight-cautionLabel",
text: cautionLabel,
x: 500,
y: 560 + cautionChangeY,
fill: "Black",
font: textFontSize
}, {
type: "text",
id: "svg-stoplight-goodLabel",
text: goodLabel,
x: 500,
y: 900 + goodChangeY,
fill: "Black",
font: textFontSize
}, {
type: "text",
id: "svg-stoplight-headerLabel",
text: kpiData.get('Header'),
x: 145,
y: -40,
fill: "Black",
font: headerFontSize
}, {
type: "text",
id: "svg-stoplight-totalLabel",
text: "Total = " + model.get('total'),
x: 100,
y: 1250,
fill: "Black",
font: textFontSize
}];
//don't add gradients if IE is > 10 or documentMode is less than 9
if (!(ie > 10 || document.documentMode < 9)) {
drawItems.push({
type: "ellipse",
id: 'test1',
radiusX: 112,
radiusY: 80,
x: 224,
y: 156,
fill: 'url(#lightGradient1)'
}, {
type: "ellipse",
radiusX: 112,
radiusY: 80,
x: 224,
y: 498,
fill: 'url(#lightGradient1)'
}, {
type: "ellipse",
radiusX: 112,
radiusY: 80,
x: 224,
y: 838,
fill: 'url(#lightGradient1)'
});
}
},
width: 210,
height: 250
});
Creation of the Panel and adding the component:
var displayPanel = Ext.create('widget.panel', {
width: 600,
height: 800,
title: 'Cost & Schedule Variance',
renderTo: 'WorkstreamStoplights',
pack: 'center',
shrinkWrap: 3,
layout: {
type: 'table',
column: 2
},
});
stoplightStore.each(function (model, idx) {
var stoplight = Ext.create('StoplightControl', {
model: model
});
displayPanel.add(stoplight);
});
displayPanel.doLayout();
As you'll be able to see from the fiddle, the Title displays properly and I have even added an item to the displayPanel on creation, but doing a .add() doesn't seem to have any effect even with the .doLayout()
Haven't dabbled in ExtJS for a long time, but the 4.2 doc states, for this method:
This method needs to be called whenever you change something on this
component that requires the Component's layout to be recalculated.
Ah, silly me. I needed to add items to my component. I needed to make the assignment in the initComponents of
this.items = drawItems;
Working fiddle

Resources