Qt Qml 3 different graphs connected to a single y-axis - qt

I want to create 3 graphs one under the other. When I move the mouse on the screen, I want to see the x value in the 3 graphs corresponding to the y value at that point. The chart I want and the outputs of my own work are as in the images. Maybe I can achieve what I want by putting a rectangle on the charts I make. But is there a more useful way or example of this?
Another problem is if I am going to continue with my own method;
When I make 3 separate charts, only the lowest one has the y axis, so there are tick counts on it. It doesn't happen in the 1st and 2nd charts. This doesn't look good either. How can I make the tick counts in the 3rd chart invisible?
When I activate the plotArea command lines and make the graphics larger and closer to each other, as in the 3rd picture, the plot description is not fully readable and 2 of the 5 numbers on the x-axis become unreadable.
for example;
output of my own code
with plotAreas open
ColumnLayout{
id: qmlWindow6GridLayout
anchors.fill: parent
ChartView {
//title: "Spline1"
id: chart1
Layout.fillWidth:true
Layout.fillHeight:true
legend.visible: true
backgroundColor: "black"
antialiasing: true
//plotArea: Qt.rect(35, 35, parent.width - 75, parent.height / 3 - 75)
SplineSeries {
//name: "Altimeter"
name: "Chart 1"
color: "red"
axisX: ValuesAxis {
visible: false
}
axisY: ValuesAxis{
labelsColor: "white"
}
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 00)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 20)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 29, 37)); y: 150 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 30, 20)); y: 200 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 45, 00)); y: 250 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 50, 00)); y: 300 }
}
}
ChartView {
//title: "Spline2"
id: chart2
Layout.fillWidth:true //yes, if wanted
Layout.fillHeight:true //yes, if wanted
legend.visible: true
backgroundColor: "black"
antialiasing: true
//plotArea: Qt.rect(35, 35, parent.width - 75, parent.height / 3 - 75)
SplineSeries {
name: "Chart 2"
color: "cyan"
axisX: ValuesAxis {
visible: false
}
axisY: ValuesAxis{
labelsColor: "white"
}
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 00)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 20)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 29, 37)); y: 150 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 30, 20)); y: 200 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 45, 00)); y: 250 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 50, 00)); y: 300 }
}
}
ChartView {
Layout.fillWidth: true
Layout.fillHeight: true
legend.visible: true
backgroundColor: "black"
antialiasing: true
//plotArea: Qt.rect(75, 75, parent.width - 125, parent.height / 3 - 125)
SplineSeries {
name: "Chart 3"
color: "purple"
axisX: DateTimeAxis {
format: "hh:mm:ss"
labelsColor: "white"
}
axisY: ValuesAxis{
labelsColor: "white"
}
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 00)); y: 50 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 15, 29, 20)); y: 100 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 29, 37)); y: 150 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 30, 20)); y: 200 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 45, 00)); y: 250 }
XYPoint { x: toMsecsSinceEpoch(new Date(0, 0, 0, 16, 50, 00)); y: 300 }
}
}
}

Related

Toggle Series programatically in lighning chart

I have UI element and I am attaching series to it
box = legendBox.addElement(UIElementBuilders.CheckBox);
series.attach(box)
Now I click the series in legendbox it toggles my line series.Is there anyway we can click the checkbox programatically ?
UICheckBox can be programmatically toggled on and off with the use of UICheckBox.setOn(isOn) method.
The following code would toggle lineSeries on and off with 1 second interval.
const ui = chart.addUIElement(UILayoutBuilders.Column)
const box = ui.addElement(UIElementBuilders.CheckBox)
lineSeries.attach(box)
setInterval(() => {
box.setOn(!box.getOn())
}, 1000)
See below for full working example where the "Diesel" series is toggled on and off programmatically through the UICheckBox.
// Extract required parts from LightningChartJS.
const {
lightningChart,
SolidLine,
SolidFill,
ColorRGBA,
AxisTickStrategies,
UIOrigins,
DataPatterns,
Themes,
UILayoutBuilders,
UIElementBuilders,
} = lcjs
// Decide on an origin for DateTime axis.
const dateOrigin = new Date(2018, 8, 1)
// ----- Cache used styles -----
const customStrokeStyle = new SolidLine({
fillStyle: new SolidFill({
color: ColorRGBA(200, 50, 50)
}),
thickness: 2
})
// Create a XY Chart.
const chart = lightningChart().ChartXY({
// theme: Themes.dark
})
// Modify the default X Axis to use DateTime TickStrategy, and set the origin for the DateTime Axis.
chart.getDefaultAxisX().setTickStrategy(AxisTickStrategies.DateTime, (tickStrategy) => tickStrategy.setDateOrigin(dateOrigin))
chart.setPadding({
right: 50
})
.setTitle('Diesel and Gasoline Price Comparison')
const diesel = [{
x: 0,
y: 1.52
},
{
x: 1,
y: 1.52
},
{
x: 2,
y: 1.52
},
{
x: 3,
y: 1.58
},
{
x: 4,
y: 2.00
},
{
x: 5,
y: 2.00
},
{
x: 6,
y: 2.00
},
{
x: 7,
y: 2.00
},
{
x: 8,
y: 2.26
},
{
x: 9,
y: 1.90
},
{
x: 10,
y: 1.90
},
{
x: 11,
y: 1.90
},
{
x: 12,
y: 1.90
},
{
x: 13,
y: 1.60
},
{
x: 14,
y: 1.60
},
{
x: 15,
y: 1.60
},
{
x: 16,
y: 1.00
},
{
x: 17,
y: 1.00
},
{
x: 18,
y: 1.00
},
{
x: 19,
y: 1.74
},
{
x: 20,
y: 1.47
},
{
x: 21,
y: 1.47
},
{
x: 22,
y: 1.47
},
{
x: 23,
y: 1.74
},
{
x: 24,
y: 1.74
},
{
x: 25,
y: 1.74
},
{
x: 27,
y: 1.5
},
{
x: 28,
y: 1.5
},
{
x: 29,
y: 1.5
}
]
const gasoline = [{
x: 0,
y: 1.35
},
{
x: 1,
y: 1.35
},
{
x: 2,
y: 1.35
},
{
x: 3,
y: 1.35
},
{
x: 4,
y: 1.90
},
{
x: 5,
y: 1.90
},
{
x: 6,
y: 1.90
},
{
x: 7,
y: 1.92
},
{
x: 8,
y: 1.50
},
{
x: 9,
y: 1.50
},
{
x: 10,
y: 1.3
},
{
x: 11,
y: 1.3
},
{
x: 12,
y: 1.3
},
{
x: 13,
y: 1.3
},
{
x: 14,
y: 1.3
},
{
x: 15,
y: 1.32
},
{
x: 16,
y: 1.40
},
{
x: 17,
y: 1.44
},
{
x: 18,
y: 1.02
},
{
x: 19,
y: 1.02
},
{
x: 20,
y: 1.02
},
{
x: 21,
y: 1.02
},
{
x: 22,
y: 1.02
},
{
x: 23,
y: 1.02
},
{
x: 24,
y: 1.02
},
{
x: 25,
y: 1.02
},
{
x: 27,
y: 1.30
},
{
x: 28,
y: 1.30
},
{
x: 29,
y: 1.30
}
]
// Add two line series.
const lineSeries = chart.addLineSeries()
.setName('Diesel')
const lineSeries2 = chart.addLineSeries()
.setName('Gasoline')
.setStrokeStyle(customStrokeStyle)
// Set the correct value to use for the data frequency.
// 1000ms * 60s * 60min * 24h
const dataFrequency = 1000 * 60 * 60 * 24
// Add the points to each Series - the X values are multiplied by dataFrequency to set the values properly on the X Axis.
lineSeries2.add(diesel.map((point) => ({
x: point.x * dataFrequency,
y: point.y
})))
lineSeries.add(gasoline.map((point) => ({
x: point.x * dataFrequency,
y: point.y
})))
// Setup view nicely.
chart.getDefaultAxisY()
.setTitle('$/litre')
.setInterval(0, 3, false, true)
// Enable AutoCursor auto-fill.
chart.setAutoCursor(cursor => cursor
.setResultTableAutoTextStyle(true)
.disposeTickMarkerX()
.setTickMarkerYAutoTextStyle(true)
)
const legend = chart.addLegendBox()
// Add Chart to LegendBox.
legend.add(chart)
const ui = chart.addUIElement(UILayoutBuilders.Column)
const box = ui.addElement(UIElementBuilders.CheckBox)
lineSeries.attach(box)
setInterval(() => {
box.setOn(!box.getOn())
}, 1000)
<script src="https://unpkg.com/#arction/lcjs#3.0.0/dist/lcjs.iife.js"></script>

How do I create larger polygons out of a smaller polygons

I would like to transform the following list of polygons:
[
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
Into a list where the adjacent polygons are joined as follows:
[
%{height: 32, width: 96, x: 0, y: 0},
%{height: 32, width: 64, x: 256, y: 0}
]
I've tried using Enum.reduce_while as follows:
Enum.reduce_while(polys, 0, fn poly, max_x ->
if poly.x - max_x <= 32, do: {:cont, max_x + 32}, else: {:halt, max_x}
end)
That works to give me the first polygon, but how do I get the subsequent polygons and is it possible to get all of them in 1 pass?
This would be a perfect use-case for Enum.chunk_while/4:
input = [
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
chunk_fun = fn
i, [] -> {:cont, i}
%{width: iw, x: ix}, %{height: ah, width: aw, x: ax, y: ay}
when ax + aw == ix ->
{:cont, %{height: ah, width: aw + iw, x: ax, y: ay}}
%{height: ih, y: iy}, %{height: ah, width: aw, x: ax, y: ay}
when ay + ah == iy ->
{:cont, %{height: ah + ih, width: aw, x: ax, y: ay}}
i, acc -> {:cont, acc, i}
end
after_fun = fn
[] -> {:cont, []}
acc -> {:cont, acc, []}
end
input
|> Enum.chunk_while([], chunk_fun, after_fun)
|> IO.inspect()
#⇒ [%{height: 32, width: 96, x: 0, y: 0},
# %{height: 32, width: 64, x: 256, y: 0}]
Please note, that the example above also handles the y-axis joins. The example is interesting due to the unusual use of a map instance as an accumulator.
I'd use Enum.reduce here. Enum.reduce_while is meant for cases when you want to stop processing the list further based on some condition. You do want to process the whole list in this case.
What I do is collect polygons in the accumulator, starting with a list with only the first polygon. Then, in each reduction, I check whether the previous polygon's x + width is the same as the new polygon's x. If it is, I merge the polygons by adding the widths, if not I prepend the polygon.
The list is collected in reverse so I use Enum.reverse after the reduction.
[
%{height: 32, width: 32, x: 0, y: 0},
%{height: 32, width: 32, x: 32, y: 0},
%{height: 32, width: 32, x: 64, y: 0},
%{height: 32, width: 32, x: 256, y: 0},
%{height: 32, width: 32, x: 288, y: 0}
]
|> Enum.reduce(nil, fn
x, nil ->
[x]
x, [h | t] ->
if h.x + h.width == x.x do
[%{h | width: x.width + h.width} | t]
else
[x, h | t]
end
end)
|> Enum.reverse()
|> IO.inspect()
Output:
[%{height: 32, width: 96, x: 0, y: 0}, %{height: 32, width: 64, x: 256, y: 0}]

Does fabricjs support radial-gradient?

I'm working with Fabric to create Radial-gradient like this
It can create very easily by css. Like this
<!DOCTYPE html>
<html>
<head>
<style>
#grad1 {
width: 100px;
height: 100px;
border-radius: 50%;
background: radial-gradient(ellipse at center, #1e5799 0%,rgba(255, 255, 255, 0) 100%);
}
</style>
</head>
<body>
<h3>Radial Gradient - Evenly Spaced Color Stops</h3>
<div id="grad1"></div>
<p><strong>Note:</strong> Internet Explorer 9 and earlier versions do not support gradients.</p>
</body>
</html>
But seem fabricJS do not support it. It only support gradient from side to side (?)
Does anyone work with this before. Please give me support.
Thank you
Yes
Some example: http://jsfiddle.net/fabricjs/58y8b/
// initialize fabric canvas and assign to global windows object for debug
var canvas = window._canvas = new fabric.Canvas('c');
// Do some initializing stuff
fabric.Object.prototype.set({
transparentCorners: false,
cornerColor: 'rgba(102,153,255,0.5)',
cornerSize: 12,
padding: 5
});
// Initialze the example
var rect1 = new fabric.Rect({
left: 100,
top: 100,
width: 100,
height: 100,
fill: '#ffda4f'
});
var rect2 = new fabric.Rect({
left: 250,
top: 100,
width: 100,
height: 100,
fill: 'rgb(111,154,211)'
});
var rect3 = new fabric.Rect({
left: 400,
top: 100,
width: 100,
height: 100,
fill: 'rgb(166,111,213)'
});
var rect4 = new fabric.Rect({
left: 100,
top: 400,
width: 100,
height: 100,
fill: '#ffda4f'
});
var rect5 = new fabric.Rect({
left: 250,
top: 400,
width: 100,
height: 100,
fill: 'rgb(111,154,211)'
});
var rect6 = new fabric.Rect({
left: 400,
top: 400,
width: 100,
height: 100,
fill: 'rgb(166,111,213)'
});
canvas.add(rect1, rect2, rect3, rect4, rect5, rect6);
/**
* setGradient linear gradients example
*/
// horizontal linear gradient
rect1.setGradient('fill', {
type: 'linear',
x1: -rect1.width / 2,
y1: 0,
x2: rect1.width / 2,
y2: 0,
colorStops: {
0: '#ffe47b',
1: 'rgb(111,154,211)'
}
});
// vertical linear gradient
rect2.setGradient('fill', {
type: 'linear',
x1: 0,
y1: -rect2.height / 2,
x2: 0,
y2: rect2.height / 2,
colorStops: {
0: '#ff4040',
1: '#e6399b'
}
});
// diagonal linear gradient
rect3.setGradient('fill', {
type: 'linear',
x1: -rect3.width / 2,
y1: -rect3.height / 2,
x2: rect3.width / 2,
y2: rect3.height / 2,
colorStops: {
0: 'rgb(166,111,213)',
0.5: 'rgba(106, 72, 215, 0.5)',
1: '#200772'
}
});
/**
* setGradient radial gradients example
*/
// radial gradient
rect4.setGradient('fill', {
type: 'radial',
r1: rect4.width / 2,
r2: 10,
x1: 0,
y1: 0,
x2: 0,
y2: 0,
colorStops: {
0: '#FF4F4F',
1: 'rgb(255, 239, 64)'
}
});
// radial gradient
rect5.setGradient('fill', {
type: 'radial',
r1: rect5.width / 2,
r2: 10,
x1: 0,
y1: 0,
x2: rect4.width / 4,
y2: rect4.height / 4,
colorStops: {
0: '#ffe47b',
0.5: 'rgb(111,154,211)',
1: 'rgb(166,111,213)'
}
});
// radial gradient
rect6.setGradient('fill', {
type: 'radial',
r1: 50,
r2: 80,
x1: 45,
y1: 45,
x2: 52,
y2: 50,
colorStops: {
0: 'rgb(155, 237, 0)',
1: 'rgba(0, 164, 128,0.4)'
}
});
canvas.renderAll();
You can do it like this:
let cir = new fabric.Circle({
left: 100,
top: 100,
radius: 30,
fill: 'rgba(0, 0, 0, 0)'
})
cir.setGradient('fill', {
type: 'radial',
r1: 30,
r2: 2,
x1: 30,
y1: 30,
x2: 30,
y2: 30,
colorStops: {
1: 'rgb(113,182,203)',
0: 'rgba(0, 0, 0, 0)'
}
});
fabricCanvas.add(cir);
fabricCanvas.renderAll();
http://jsfiddle.net/Kyashar/z6428pta/

highcharts, four aeraranges with linear gradients

I'm trying to create chart in Highcharts with four arearanges and one line. I'm doing my best to get something like on image:
arearanges
I'v managed to do something like this:
$(function () {
var rangesHI = [
[1246406400000, 90, 75],
[1248998400000, 90, 75]
],
rangesME = [
[1246406400000, 75, 60],
[1248998400000, 75, 60]
],
rangesNO = [
[1246406400000, 60, 35],
[1248998400000, 60, 35]
],
rangesLO = [
[1246406400000, 35, 15],
[1248998400000, 35, 15]
],
averages = [
[1246406400000, 31.5],
[1246492800000, 32.1],
[1246579200000, 33],
[1246665600000, 33.8],
[1246752000000, 31.4],
[1246838400000, 31.3],
[1246924800000, 38.3],
[1247011200000, 35.4],
[1247097600000, 36.4],
[1247184000000, 47.7],
[1247270400000, 47.5],
[1247356800000, 37.6],
[1247443200000, 47.7],
[1247529600000, 46.8],
[1247616000000, 47.7],
[1247702400000, 46.3],
[1247788800000, 47.8],
[1247875200000, 48.1],
[1247961600000, 57.2],
[1248048000000, 54.4],
[1248134400000, 53.7],
[1248220800000, 55.7],
[1248307200000, 54.6],
[1248393600000, 55.3],
[1248480000000, 45.3],
[1248566400000, 55.8],
[1248652800000, 65.2],
[1248739200000, 74.8],
[1248825600000, 44.4],
[1248912000000, 55],
[1248998400000, 43.6]
];
$('#container').highcharts({
title: {
text: null
},
xAxis: {
type: 'datetime'
},
yAxis: {
max:90,
min:20,
title: {
text: null
}
},
series: [{
name: 'RH',
data: averages,
zIndex: 1
}, {
data: rangesHI,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [0, 0, 0, 300],
stops: [
[0, 'rgba(255,0,0, 0.2)'],
[1, 'rgba(255,0,0, 1)']
]
},
zIndex: 0
}, {
data: rangesME,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [300, 0, 300, 400],
stops: [
[0, 'rgba(237,230,126, 0.2)'],
[1, 'rgba(237,230,126, 1)']
]
},
zIndex: 0
}, {
data: rangesNO,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [500, 0, 500, 600],
stops: [
[0, 'rgba(104,217,91, 0.2)'],
[1, 'rgba(104,217,91, 0.7)']
]
},
zIndex: 0
}, {
data: rangesLO,
type: 'arearange',
lineWidth: 0,
fillColor: {
linearGradient: [0, 0, 0, 220],
stops: [
[0, 'rgba(91,187,217, 0.2)'],
[1, 'rgba(91,187,217, 0.7)']
]
},
zIndex: 0
}]
}, function (chart) {
chart.renderer.text('EKSTREMALNA', 80, 95).css({
fontSize: '16pt',
color: 'rgba(255,0,0, 1)'
}).add();
chart.renderer.text('WYSOKA', 80, 145).css({
fontSize: '16pt',
color: 'rgba(237,230,126, 1)'
}).add();
chart.renderer.text('KOMFORTOWA', 80, 225).css({
fontSize: '16pt',
color: 'rgba(104,217,91, 01)'
}).add();
chart.renderer.text('NISKA', 80, 305).css({
fontSize: '16pt',
color: 'rgba(91,187,217, 1)'
}).add();
});
http://jsfiddle.net/qazopap4/1/ but this is far from what I'v expected.
I can't make linear gradient for each arearange separately.
You can use plotBands which allows you to apply gradients.
yAxis: {
plotBands: [{
from: 60,
to: 90,
color: {
linearGradient: [0, 0, 0, 300],
stops: [
[0, 'rgba(255,0,0, 0.2)'],
[1, 'rgba(255,0,0, 1)']
]
}
}],
max: 90,
min: 20,
title: {
text: null
}
},
Example: http://jsfiddle.net/pag5qgsm

Tweening polygon Kinetic JS

Can I change the size of polygon wchich I defined by points?
var pierwszy = new Kinetic.Polygon({
points: [0, 0, 150, 0, 80, 150, 0, 150],
fillPatternImage: images.img1,
stroke: 'black',
strokeWidth: 5,
});
I have tried to just change points and add to tween atriubutes, but it doesn't work.
scaleX and scaleY work very well, but the background image is bluring.
Any ideas?
I don't know if this is useful for you,In my situation is ,I want to change the shape of the polygon with a tween:
poly1= new Kinetic.Polygon({
points: [0, 0, 150, 0, 80, 150, 0, 150],
fill: shadowLightColor,
stroke: '#bbbbbb',
strokeWidth: 1
});
layer.add(poly1);
poly1.tween = new Kinetic.Tween({
node: poly1,
duration: 1,
points: [0, 0, 300, 0, 200, 150, 0, 150],
easing: Kinetic.Easings.StrongEaseInOut
}).play();

Resources