Particle system on event - aframe

I'd like to have the particle system appear at the end of my project, like confetti. What I have is this, but it is not working, nor is setting the visibility to false, then true. Not sure which attribute I can use to set the visibility off, then on.
html:
<a-entity id="confetti" particle-system="accelerationSpread: 20 0 20; color: white; enabled: false; particleCount: 300; opacity: 0.3; preset: default; size: 0.5; velocityValue: 0 15 0" position="5.584 1.250 -1.4" ></a-entity>
js:
if (score == 7) {
function tada() {
congrats.setAttribute('visible', true);
confetti.setAttribute('enabled', true);
}
}
Thanks!

confetti.object3D.visible = false or confetti.removeAttribute('particle-system')

You can use
AFRAME.utils.entity.setComponentProperty(confetti, 'particle-system.enabled', true);
Apparently setAttribute doesn't support multiple levels of components.
It's documented here:
https://aframe.io/docs/1.0.0/core/utils.html#setcomponentproperty-entity-componentname-value-delimiter

Related

Proper way to set a child item property in QML

Everyone knows about how to set a background for Buttons, Popups etc via the background property of these elements. But I am wondering, how can I create such a property myself for my own custom elements? I found a way but it looks pretty ugly and I can't seem to find the qml code for Button, Popup etc where said property is defined. So i played a bit and came up with the idea of using Bindings like this:
Item {
id: root
property Item background: Rectangle {
color: "red"
}
Binding {
target: root.background
property: "parent"
value: root
}
Binding {
target: root.background
property: "anchors.fill"
value: root
when: root.background.parent == root
delayed: true
}
}
As mentioned that looks pretty tiresome if you need to declare a lot of properties of the child. So, how does Qt do it or what is the proper way of doing it?
// ItemWithBackground.qml
Item {
property alias background: backgroundLoader.sourceComponent
Loader {
id: backgroundLoader
anchors { fill: parent }
sourceComponent: Rectangle { color: 'red' } // default background implementation
}
}
// Usage example:
ItemWithBackground {
background: Rectangle {
color: 'green'
}
}
If you’re on a recent Qt version, have a look at using inline components. They allow you to create API’s like this easily.

Resize the cursor

I'm building a drawing application (Like paint or Sketchpad) and I need to resize my cursor depending on of the line width of the pencil. The problem is, apparently, you can't resize your cursor. The solution that I found is to use a custom cursor (the normal cursor is changed for an image) and to resize the image. The thing is, I don't know if I need a function to do that or I can directly change the size of the image via SCSS (CSS).
Here's what I've done so far:
private setCursor(cursorType: DrawingCursor): void {
this.Canvas.setAttribute("style", "cursor:url(" + cursorType + "), auto;");}
The cursorType is the url of the custom cursor.
I'm doing this from an angular 8 project (in Typescript).
Thank you !
You can use NgClass binding to implement it. This way the Angular binding takes care of applying the CSS classes so you don't need to set styles manually.
To implement this solution first define the CSS classes for the canvas and the different cursor sizes. For example:
.myCanvas {
width: 400px;
height: 400px;
background-color: green;
}
.brush18px {
cursor: url('brush18px.png'), auto;
}
.brush24px {
cursor: url('brush24px.png'), auto;
}
.brush36px {
cursor: url('brush36px.png'), auto;
}
Then in the component you define a property that will provide the classes for the canvas and a property for the size of the brush. For example:
#Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
})
export class AppComponent {
name = 'Angular';
#Input() cursorSize = '18';
get canvasClasses() {
return {
myCanvas: true,
brush18px: this.cursorSize === '18',
brush24px: this.cursorSize === '24',
brush36px: this.cursorSize === '36',
};
};
}
The canvasClasses property must return an object that specifies for each CSS class name if it is applied or not by setting the value to true or false. I use a getter property here so the values update automatically when the size changes.
Now you can bind this in the template and the cursor will automatically update based on the cursorSize value.
Here is how the template looks like:
<canvas [ngClass]="canvasClasses"></canvas>
<br/>
<select [(ngModel)]="cursorSize">
<option>18</option>
<option>24</option>
<option>36</option>
</select>
I have created also a working StackBlitz sample so you can see it in action.
Another possible solution based on the comment on the first answer. This is more of a workaround solution where you hide the actual cursor and move around an image instead so it looks like it is the cursor. This was inspired by the second answer on this post about resizing a cursor image.
I implemented this solution in Angular using a directive that you add to the canvas element in the template. The directive takes as the main parameter the image to show as the cursor and has an additional parameter for the size for the image. I recommend an SVG image that resizes well. Still it is possible to use also a standard image.
Here is the implementation of the Directive for an SVG image:
#Directive({
selector: '[svgCursor]'
})
export class SvgCursorDirective {
private cursorSizeValue: number = 16;
#Input('svgCursor') public svgImage: SVGSVGElement;
#Input() public set cursorSize(cursorSize: number) {
this.cursorSizeValue = cursorSize;
this.updateCursorSize();
}
constructor(el: ElementRef) {
el.nativeElement.style.cursor = 'none'; // hides the browser cursor
}
#HostListener('mouseenter') onMouseEnter() {
// makes image visible only when mous enters the element
this.svgImage.style.visibility = 'visible';
}
#HostListener('mousemove', ['$event']) onMouseMove(e: MouseEvent) {
// draws the image at the mouse position
this.svgImage.style.left = e.clientX.toString();
this.svgImage.style.top = (e.clientY - this.cursorSizeValue).toString();
}
#HostListener('mouseleave') onMouseLeave() {
// hides image when the mouse leaves the element
this.svgImage.style.visibility = 'hidden';
}
private updateCursorSize() {
if (this.svgImage != null) {
this.svgImage.style.width = this.cursorSizeValue.toString();
this.svgImage.style.height = this.cursorSizeValue.toString();
}
}
}
Once you have the directive you can use it in the following way inside a component template:
<svg #cursorImage class="cursor" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none"/><path d="M7 14c-1.66 0-3 1.34-3 3 0 1.31-1.16 2-2 2 .92 1.22 2.49 2 4 2 2.21 0 4-1.79 4-4 0-1.66-1.34-3-3-3zm13.71-9.37l-1.34-1.34c-.39-.39-1.02-.39-1.41 0L9 12.25 11.75 15l8.96-8.96c.39-.39.39-1.02 0-1.41z"/></svg>
<canvas class="myCanvas" [svgCursor]="cursorImage" [cursorSize]="cursorSize"></canvas>
As you can see you need to add a template reference variable to the image so you can pass it as a parameter to the svgCursor directive.
Also important for this to work you need to set the correct CSS styles to the image to disable things that are not needed. It is also set to invisble so it becomes visible only when the mouse enters te canvas.
This are the styles I used:
.myCanvas {
width: 400px;
height: 400px;
background-color: lightgreen;
}
.cursor {
position: absolute;
cursor: none;
pointer-events: none;
visibility: hidden;
}
I have created also a working StackBlitz sample so you can see how this works.

d3js Opacity Transition Not Working as Expected

I have a group I want to animate form 0 opacity to 1. I've animated it from 1 to 0 fine, but going the other way is strange.
The below code-
showSelection.transition()
.duration(animate ? 300 : 0)
.style('opacity', 1)
.on('end', () => {
selection.style('pointer-events', 'inherit');
});
Is resulting in opacity: 9.09815e-08; pointer-events: none;
I made the opacity value something very high .style('opacity', 100000000) and now i'm getting some more like opacity: 9.25965; pointer-events: none;
Does anyone know what would cause this?
I guess I needed to set the opacity to 0 before animating it to 1.
showSelection.transition()
.style('opacity', 0)
.duration(animate ? 300 : 0)
.style('opacity', 1)
.on('end', () => {
selection.style('pointer-events', 'inherit');
});

Dynamic Variable Names with Less

I'm trying to assign some dynamic variable names using less (using it for the first time) ... but nothing I've tried seems to work. After looking through all the documentation, I came up with this, but it's still not working:
// jellybeans
#opacity: 1;
#black-jellybeans: rgba(59,59,59,#opacity); // #3b3b3b
#red-jellybeans: rgb(207,106,76,#opacity); // #cf6a4c
#green-jellybeans: rgba(153,173,106,#opacity); // #99ad6a
#yellow-jellybeans: rgba(216,173,76,#opacity); // #d8ad4c
#blue-jellybeans: rgba(89,123,197,#opacity); // #597bc5
#magenta-jellybeans: rgba(160,55,176,#opacity); // #a037b0
#cyan-jellybeans: rgba(113,185,248,#opacity); // #71b9f8
#white-jellybeans: rgba(173,173,173,#opacity); // #adadad
// the palette to use
#palette: "jellybeans";
#black: "black-#{palette}";
#red: "red-#{palette}";
#green: "green-#{palette}";
#yellow: "yellow-#{palette}";
#blue: "blue-#{palette}";
#magenta: "magenta-#{palette}";
#cyan: "cyan-#{palette}";
#white: "white-#{palette}";
Any suggestions?
use:
#cyan: "cyan-#{palette}";
p{
color: ##cyan;
}
or
#whitename: "white-#{palette}";
#white: ##whitename;
p{
color: #white;
}

Stop div from sliding up when it's textbox is focused on

I'm trying to make the upper panel of my application to have top property to be -80px by default so it's invisible except of a small part of it. And when the user hover with his mouse on that part, it slides down again.
The problem is, this div has a textbox, i want the div to stop sliding up when the user is typing on this textbox even if he move his mouse pointer away, but unfortunately don't know how to do this, here's my code :
index.html
<div id="taskInput">
<div id="controllers">
<input type="text" name="mainTask" id="mainTask">
<button id="addMain">Add</button>
<button id="resetMain">Reset</button>
</div>
</div>
css of this part :
#taskInput {
background: red;
width:606px;
height:43px;
padding: 22px;
box-shadow: 0px 3px 4px -3px black;
position: absolute;
z-index : 0;
top:0px;
}
script.js
$(function(){
$("#taskInput").delay(400).animate({top:-80}, 500,function(){});
$("#taskInput").mouseover(
function(){
$(this).stop().animate({top:0}, 200, function(){});
});
$("#taskInput").mouseout(function(evt){
$(this).stop().animate({top:-80}, 200, function(){});
})
$("#mainTask").focus(function(){
//i though i can put something here to stop mouseout event or something
})
})
I've changed my mind from my comment, there's no need to unbind the events or use a global variable to track it. You can use document.activeElement to get the currently focused element on the page, and compare its id to the id of your <input>, like so:
$("#taskInput").mouseout(function(evt){
if(document.activeElement.id !== 'mainTask') {
$(this).stop().animate({top:-80}, 200, function(){});
}
});
Working DEMO
add a flag to the animate to top and change it in the focus function
i have not tested this but it should work
$(function(){
writing = false;
$("#taskInput").delay(400).animate({top:-80}, 500,function(){});
$("#taskInput").mouseover(
function(){
$(this).stop().animate({top:0}, 200, function(){});
});
$("#taskInput").mouseout(function(evt){
if(writing == false){
$(this).stop().animate({top:-80}, 200, function(){});
}
})
$("#mainTask").focus(function(){
//i though i can put something here to stop mouseout event or something
writing = true
})
$("#mainTask").focusout(function(){
//i though i can put something here to stop mouseout event or something
writing = false
})
})
jsFiddle DEMO
Easiest way is to give the #mainTask a data-focus attribute set to true, then when doing the mouseout on #taskInput, make sure it is False before animating the slideUp.
$(function(){
// ... code
$("#taskInput").mouseout(function(evt){
console.log($('#mainTask').data('focus'));
if ($('#mainTask').data('focus') === false) {
$(this).stop().animate({top:-80}, 200, function(){});
}
})
$("#mainTask").on({
focus: function(){
$(this).data('focus', true);
},
blur: function () {
$(this).data('focus', false);
}
});
})
​
I guess, you could also give this a try:
$('#taskInput').delay(400).animate({top:-80},500);
$('#taskInput').mouseover(function()
{
$(this).stop().animate({top:0},200);
});
$('#taskInput').mouseout(function()
{
if(!$('#mainTask').is(':focus'))
{
$(this).stop().animate({top:-80},200);
}
});
DEMO
Edit:
You could also add this to your code:
$('#mainTask').blur(function()
{
$('#taskInput').stop().animate({top:-80},200);
});
DEMO 2
in the $("#mainTask").focus event handler you can set a global boolean variable to true, set it to false in an blur event handler and check on the value of that variable in the #taskInput mouseout event handler
var preventSlide = false;
$("#taskInput").mouseout(function(evt){
if (!preventSlide) {
$(this).stop().animate({top:-80}, 200, function(){});
}
})
$("#mainTask").focus(function(){
preventSlide = true;
})
$("#mainTask").blur(function(){
preventSlide = false;
})
$(function(){
var flag=true;
$("#taskInput").on('mouseenter mouseleave', function(e) {
if (flag) $(this).stop().animate({top: e.type=='mouseenter'?0:-80}, 200);
}).delay(400).animate({top:-80}, 500);
$("#mainTask").on('blur focus', function(e) {
flag=e.type=='blur';
});
});​
FIDDLE

Resources