QML Context2D how to fill two ellipses with different colors? - qml

I want to create an n segmente color bar, where its end points are semi circles. Here is my code so far:
File main.qml
import QtQuick 2.12
import QtQuick.Window 2.12
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
ResultBar{
anchors.centerIn: parent
vmColorArray: ["#0000ff", "#00ff00", "#ff0000"];
id: test;
}
}
File ResultBar.qml
import QtQuick 2.0
Item {
id: resultBar
width: 200
height: 20
property var vmColorArray: [];
Canvas {
id: rightTip
width: parent.width
height: parent.height
contextType: "2d"
anchors.right: parent.right
anchors.verticalCenter: parent.verticalCenter
onPaint: {
if (vmColorArray.length < 2) return;
var ctx = rightTip.getContext("2d");
ctx.reset();
var y = 0;
var n = vmColorArray.length;
var w = width/n;
// Left end
ctx.ellipse(0,y,height,height);
ctx.fillStyle = vmColorArray[0];
ctx.fill();
ctx.closePath();
// Right end
ctx.ellipse(width-height,y,height,height);
ctx.fillStyle = vmColorArray[n-1];
ctx.fill();
var x = 0;
for (var i = 0; i < n; i++){
if (i === 0) x = height/2;
else x = i*w;
var wd
if (i === n-1) wd = w - height/2;
else wd = w
ctx.fillStyle = vmColorArray[i];
ctx.fillRect(x,y,wd,height)
}
}
}
}
My problem is that coloring the right end ALSO colors the left end. Here is what it looks like:
So my question is how do I tell the canvas to fill one of the circles and THEN fill the other without refilling the previous one?

I've figured it out. Copying ONLY the relevant code:
// Left end
ctx.fillStyle = vmColorArray[0];
ctx.ellipse(0,y,height,height);
ctx.fill();
//ctx.closePath();
// Right end
ctx.beginPath()
ctx.fillStyle = vmColorArray[n-1];
ctx.ellipse(width-height,y,height,height);
ctx.fill();
The key was to begin a new path!! Hope this helps someone!

Related

How to change the direction of a group sprite based on a condition in Phaser 3

I'm using Phaser 3 and tried doing this:
class Bee extends Phaser.GameObjects.Sprite {
constructor(config) {
super(config.scene, config.x, config.y, 'bee');
config.scene.add.existing(this);
config.scene.physics.add.existing(this);
this.initial = [config.x, config.y];
this.x = config.x;
this.y = config.y;
this.speed = 5;
}
preUpdate() {
if (this.y < this.initial[1] - 100) {
this.speed *= -1;
}
if (this.y > this.initial[1] + 100) {
this.speed *= -1;
}
this.y += this.speed;
this.setY(this.y);
}
}
I want a Bee object to move down 100 px then move up and then repeat, but it doesn't seem to work.
In my scene I created a object:
bees = this.physics.add.group();
let bee = new Bee({scene:scene, x: 100, y:200})
bee.setScale(0.5);
bee.allowGravity = false;
bees.add(bee);
I'll have multiple Bee sprites in the game.
You could solve the up and down movement with a simple tween (https://photonstorm.github.io/phaser3-docs/Phaser.Tweens.Tween.html).
A tween changes/moves the selected property (or multiple properties) between a starting and an end position. In your case, I would use it to change the y property of the bee physic body velocity.
You can do alot with a tween, without the need to calculate speed, next position and so on. You just have to tweak the properties of the tween config, to get the desired movement/animation.
Here a working example:
(Update: Now with a few bees in the group and an 'offset' for the flight pattern)
class Bee extends Phaser.GameObjects.Sprite {
constructor(config) {
super(config.scene, config.x, config.y, 'bee');
config.scene.add.existing(this);
config.scene.physics.add.existing(this);
this.x = config.x;
this.y = config.y;
config.scene.tweens.add({
targets: this.body.velocity,
y: { from: -100, to: 100 },
ease: Phaser.Math.Easing.Quadratic.InOut,
yoyo: true,
repeat: -1,
duraton: 1000,
// just to create a interesting offset for the example
delay: Phaser.Math.Between(0,6) * 200
});
}
}
function create(){
let bees = this.physics.add.group();
for(let i=0; i < 10 ; i++){
let bee = new Bee({scene: this,
x: i * -100 ,
y: 50 });
bees.add(bee);
}
bees.setVelocity(100,0)
}
const config = {
type: Phaser.AUTO,
width: 400,
height: 200,
physics: {
default: 'arcade',
},
scene: {
create
}
};
const game = new Phaser.Game(config);
<script src="https://cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.js"></script>

View not rendering images correctly in React-Native

I am trying to display images in a view but the images are not getting rendered according to the x and y coordinates provided.
The var all_dim[i] is a string of the form X_coord,Y_coord, Height, Width
public styles = StyleSheet.create({
scroll_layouts: {
height: 100,
zIndex: 40,
backgroundColor: "#fff",
},
Lay_view: {
width: 100,
height: 200,
transform: [
{ translateX: 0},
{ translateY: 0},
]
}
});
public displayLayout()
{
if(this.props.index == 2)
{
var to_disp = [];
var all_layouts = this.props.data_string.split('&');
for(var j = 0;j < all_layouts.length - 1;j++)
{
var all_dim = all_layouts[j].split(";");
var xyz=[];
var images_arr = this.props.arr_img;
for(var i = 0;i < all_dim.length - 1;i++)
{
var image_fill = images_arr[i].uri;
var indivi_elems = all_dim[i].split(',');
var h = parseFloat(indivi_elems[2]);
var w = parseFloat(indivi_elems[3]);
var xc = parseFloat(indivi_elems[0]);
var yc = parseFloat(indivi_elems[1]);
xyz.push(<Image key = {i} source = {{uri: image_fill}} style = {{height: h, width: w,transform: [{ translateX: xc},{ translateY: yc},{scaleX:1},{scaleY:1}]}}/>);
}
var hjk = <View key = {j} style = {this.styles.Lay_view}>{xyz}</View>;
to_disp.push(hjk);
}
return (
<ScrollView horizontal = {true} style = {this.styles.scroll_layouts}>
{to_disp}
</ScrollView>)
}
}
I expect the images to be displayed according to the coordinates provided and not one below the other.
Expected layout of images in output
Output rendered
The children of the view should have their position prop set to 'absolute'

In Vue, how can I batch a bunch of changes to a DOM element?

I'm doing an animation, where a thumbnail blows up to take up the whole screen. The first step is to get the element, change it's position to absolute and assign explicitly the dimensions and position that it's currently occupying, using a style object. Then I do my animation.
Most of the time it works nicely, but I seem to be getting DOM renders that catch my element in an intermediate state, it's position changed to absolute but the dimensions not set. In Vue, is there a way of grouping into a single batch a bunch of updates to an element?
var me = this;
var outer = this.$refs.outer;
if (!this.vueStore.previewing) {
var rect = outer.getBoundingClientRect();
this.elStyle.height = rect.bottom - rect.top;
this.elStyle.width = rect.right - rect.left;
this.elStyle.top = rect.top;
this.elStyle.left = rect.left;
this.elStyle.zIndex = 100;
this.elStyle.position = 'absolute';
this.elStyle.transition = 'all 0.5s ease-in-out';
setTimeout(function () {
this.elStyle.top = this.vueStore.contentRect.top;
this.elStyle.left = this.vueStore.contentRect.left;
this.elStyle.height = this.vueStore.contentRect.bottom;
this.elStyle.width = this.vueStore.contentRect.right;
}, 300);
} else {...
You should assign elStyle in 1 time
var me = this;
var outer = this.$refs.outer;
if (!this.vueStore.previewing) {
var rect = outer.getBoundingClientRect();
me.elStyle = Object.assign({}, me.elStyle, {
height: rect.bottom - rect.top,
width: rect.right - rect.left,
top: rect.top,
left: rect.left,
zIndex: 100,
position: absolute
})
setTimeout(function () {
me.elStyle = Object.assign({}, me.elStyle, {
height: me.vueStore.contentRect.bottom - 50;,
width: me.vueStore.contentRect.right,
top: me.vueStore.contentRect.top,
left: me.vueStore.contentRect.left,
})
}, 300);
}

react-native requestanimationframe - flicker - freeze - app crash

am learning to build app using react-native and below is the component code that am using. The problem is - when I simulate this app - it crashes in few seconds. I couldnt understand what is causing this problem. Can someone please suggest.
I am trying to animate a canvas circle using requestAnimationFrame in this component.
Thank you ..
import React, { Component } from 'react';
import {
Platform,
StyleSheet,
Text,
View,
Dimensions
} from 'react-native';
import Canvas from 'react-native-canvas';
export default class ThreeDiscs extends Component{
constructor(props){
super(props);
this.state = {
context: null,
screen: {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height
},
a: 0,
b: 0,
c: 100,
d: 100
};
this.coordinates = {
a: 0,
b: 0,
c: 100,
d: 100
};
this.directions = {
increment: 5,
direction: 0
};
this.discs = [
{
x: 150,
y: 250,
lastX: 150,
lastY: 250,
velocityX: -3.2,
velocityY: 3.5,
radius: 10,
innerColor: 'rgba(255,255,0,1)',
middleColor: 'rgba(255,255,0,0.7)',
outerColor: 'rgba(255,255,0,0.5)',
strokeStyle: 'gray',
}
];
this.numDiscs = this.discs.length;
}
rendercanvas = (canvas) => {
canvas.width = this.state.screen.width;
canvas.height = this.state.screen.height;
const context = canvas.getContext('2d');
this.setState({context: context});
context.fillStyle = 'purple';
context.fillRect(0,0,100,100);
this.drawBackground(context);
this.update(context);
this.draw(context);
this.animatecanvas(context);
}
drawBackground(context) {
var STEP_Y = 12,
i = this.state.screen.height;
context.strokeStyle = 'lightgray';
context.lineWidth = 0.5;
while(i > STEP_Y*4) {
context.beginPath();
context.moveTo(0, i);
context.lineTo(context.canvas.width, i);
context.stroke();
i -= STEP_Y;
}
context.save();
context.strokeStyle = 'rgba(100,0,0,0.3)';
context.lineWidth = 1;
context.beginPath();
context.moveTo(35,0);
context.lineTo(35,context.canvas.height);
context.stroke();
context.restore();
}
update(context) {
var disc = null;
for(var i=0; i < this.numDiscs; ++i) {
disc = this.discs[i];
if (disc.x + disc.velocityX + disc.radius > context.canvas.width ||
disc.x + disc.velocityX - disc.radius < 0)
disc.velocityX = -disc.velocityX;
if (disc.y + disc.velocityY + disc.radius > context.canvas.height ||
disc.y + disc.velocityY - disc.radius < 0)
disc.velocityY= -disc.velocityY;
disc.x += disc.velocityX;
disc.y += disc.velocityY;
}
}
draw(context) {
var disc = this.discs[i];
for(var i=0; i < this.numDiscs; ++i) {
disc = this.discs[i];
context.save();
context.beginPath();
context.arc(disc.x, disc.y, disc.radius, 0, Math.PI*2, false);
context.fillStyle = '#000';
context.strokeStyle = disc.strokeStyle;
context.fill();
context.stroke();
context.restore();
}
}
animatecanvas(context){
context.clearRect(0,0,this.state.screen.width,this.state.screen.height);
this.drawBackground(context);
this.update(context);
this.draw(context);
requestAnimationFrame(() => {this.animatecanvas(context)});
}
render(){
return(
<Canvas ref={this.rendercanvas} />
);
}
}

famous: scrollview within scrollview

I'm trying to create a layout (using famous.js) similar to the BBC News native app; a vertical ScrollView, within which are numerous horizontal ScrollViews. I've got both 'working' to the extent that everything renders and the horizontal scrollers work perfectly. My issue is that the vertical scroll event won't fire if the user swipes a surface within a horizontal ScrollView. If i touch an area outside the horizontal scrollers, the vertical scroller will do its job and scroll... vertically
Does anyone know what i'm missing? I have a feeling that a RenderNode may be needed, but have had no luck so far. I'm just getting to grips with Famous. What i've seen so far is amazing, but not being able to figure this out is really getting to me...
Uber thanks in advance if anyone can help...
/*globals define*/
define(function(require, exports, module) {
// import dependencies
var Modifier = require('famous/core/Modifier');
var Engine = require('famous/core/Engine');
var Surface = require('famous/core/Surface');
var HeaderFooterLayout = require('famous/views/HeaderFooterLayout');
var Scrollview = require('famous/views/Scrollview');
var ContainerSurface = require('famous/surfaces/ContainerSurface');
var mainContext = Engine.createContext();
var layout = new HeaderFooterLayout({
headerSize: 50,
footerSize: 50
});
// create app header and add to layout
var appHeader = new ContainerSurface({
size: [undefined, 50],
classes: ['app-header']
});
appHeader.add(new Surface({
size: [undefined, 50],
content: 'Site Name',
classes: ['app-header__title'],
properties: {
lineHeight: '50px',
textAlign: 'center'
}
}));
layout.header.add(appHeader);
// create page container surface
var page = new ContainerSurface({
properties: {
top: '0'
}
});
// returns a horizontal ScrollView containing
function createCategory() {
var categoryScroll = new Scrollview({
direction: 0,
});
var surfaces = [];
categoryScroll.sequenceFrom(surfaces);
for (var i = 0, temp; i < 7; i++) {
var temp = new Surface({
size: [128, 128],
content: 'surface' + (i + 1),
properties: {
backgroundColor: '#fff',
borderColor: '#303030',
borderStyle: 'solid',
borderWidth: '0px',
borderRightWidth: '4px',
borderLeftWidth: '4px'
}
});
temp.pipe(categoryScroll);
surfaces.push(temp);
}
return categoryScroll;
}
// returns a vertical page scroll
function createPageScroll() {
// create array of horizontal ScrollViews
categories = [];
for (var i = 0; i < 7; i++) {
categories.push(createCategory());
};
var pageScroll = new Scrollview();
var surfaces = [];
for (var i = 0; i < 7; i++) {
temp = new ContainerSurface({
size: [window.innerWidth, 136],
});
temp.add(categories[i]);
surfaces.push(temp);
pageScroll.sequenceFrom(surfaces);
temp.pipe(pageScroll);
};
return pageScroll;
}
layout.content.add(createPageScroll());
mainContext.add(layout);
});
I see you figured it out, but I thought I would post a clean working example for anyone that needed a starting point.. So here it is..
To answer the question, Yes, you needed to pipe your events from the surfaces to each of the scrollviews
var Engine = require("famous/core/Engine");
var Surface = require("famous/core/Surface");
var View = require("famous/core/View");
var Scrollview = require("famous/views/Scrollview");
var ContainerSurface = require("famous/surfaces/ContainerSurface");
var context = Engine.createContext();
var surfaces1 = [];
var surfaces2 = [];
var scrollers = [];
scroll_v_cont = new ContainerSurface({
size:[300,300],
properties: { overflow: 'hidden' }
});
var scroll_v = new Scrollview({ direction: 1 });
scroll_v.sequenceFrom(scrollers);
scroll_v_cont.add(scroll_v);
var scroll_h1_cont = new ContainerSurface({
size:[300,300],
properties: {overflow: 'hidden'}
});
var scroll_h1 = new Scrollview({ direction: 0});
scroll_h1.sequenceFrom(surfaces1);
scroll_h1_cont.add(scroll_h1);
var scroll_h2_cont = new ContainerSurface({
size:[300,300],
properties: { overflow: 'hidden'}
})
var scroll_h2 = new Scrollview({ direction: 0})
scroll_h2.sequenceFrom(surfaces2);
scroll_h2_cont.add(scroll_h2);
scrollers.push(scroll_h1_cont);
scrollers.push(scroll_h2_cont);
for (var i = 0; i < 4; i++) {
var surface1 = new Surface({
content: "Surface: " + (i + 1),
size: [300, 300],
properties: {
backgroundColor: "hsl(" + (i * 360 / 8) + ", 100%, 50%)",
lineHeight: "200px",
textAlign: "center"
}
});
surface1.pipe(scroll_v);
surface1.pipe(scroll_h1);
surfaces1.push(surface1);
var surface2 = new Surface({
content: "Surface: " + (i + 1),
size: [300, 300],
properties: {
backgroundColor: "hsl(" + (i * 360 / 8 + (360 / 8)*4) + ", 100%, 50%)",
lineHeight: "200px",
textAlign: "center"
}
});
surface2.pipe(scroll_v);
surface2.pipe(scroll_h2);
surfaces2.push(surface2);
};
context.add(scroll_v_cont);
the famous-flex FlexScrollView supports vertical & horizontal scrolling restrictions when embedding one scrollview in another. It is described in more detail at the bottom of the FlexScrollView tutorial:
https://github.com/IjzerenHein/famous-flex/blob/master/tutorials/FlexScrollView.md