cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Need help navigating or using the PTC Community? Contact the community team. X

How to create a fade in and fade out effect for a 3D Image when it is triggered for visibility.

Ace_Rothstein
11-Garnet

How to create a fade in and fade out effect for a 3D Image when it is triggered for visibility.

 
1 ACCEPTED SOLUTION

Accepted Solutions

Hello @Ace_Rothstein ,

you can achieve this effect also with javascript. Here is an sample code which will work generally for widget which supports the opacity property e.g. 3D widgets modelItem, model or 3DImage etc. :

 

$scope.fadeOut = function(widget, time, interval) {
  let w = (widget.opacity !== undefined ? widget : $scope.view.wdg[widget]); //wiget name or widget it self
  if (time <= 0 || interval <= 0 || w.opacity === undefined) { throw "Cannot fade this widget"; }
  let steps = Math.floor(time / interval);
  let opDelta = w.opacity / steps;
  return $interval(() => w.opacity = (opDelta < w.opacity) ? (w.opacity - opDelta) : 0, interval, steps);
}

$scope.fadeIn = function(widget, targetOpacity,time, interval) {
  let w = (widget.opacity !== undefined ? widget : $scope.view.wdg[widget]);
  if (time <= 0 || interval <= 0 || w.opacity === undefined) { throw "Cannot fade this widget"; }
  let steps = Math.floor(time / interval);
  let opDelta = targetOpacity / steps;
  return $interval(() => w.opacity = (targetOpacity > w.opacity) ? (w.opacity + opDelta) : targetOpacity, interval, steps);
}

//call of the fadeOut for different widget with different time
$scope.testFadeOut= function()
{
  
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['modelItem-1'],2000,200) } ,500)
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['modelItem-2'],4000,200) } ,1500) 
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['modelItem-3'],6000,200) } ,2500)
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['model-1']    ,5000,200) } ,3500)
}
/call of the fadeIn for different widget with different time
$scope.testFadeIn= function()
{
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['modelItem-1'],0.8,2000,200) } ,500)
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['modelItem-2'],0.9,4000,200) } ,1500)
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['modelItem-3'],1.0,6000,200) } ,2500)
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['model-1']     ,1.0,5000,200) } ,3500)
}

 

 

So this example will work where  it will  fade In or fade out different widgets (here modelItems and model) with different speed/time.

Here the arguments are

-the widget

-the time where the fade in/out should be completed,

-the interval step

-for fade in function the target opacity

Here when I tested it in a project:

 

2020-09-28_11-49-43.jpg

 

You can test it as mentioned for widget which supports the opacity property. The $timeout service was used to call the functions with some delay.

You mentioned "to trigger" in your question. I think one possible way to trigger a function call depending on value change is to use $watch construct. Example:

 

:

 

$scope.$watch('view.wdg["model-1"].currentStep', function(val) {
 //will call this function when the currentStep will chnage
if(val==2) $scope.testFadeOut();
if(val==4) $scope.testFadeIn();
    $scope.$applyAsync();
});

 

 

Here we will call the function when the value of  a widget property e.g. here currentStep (widget 'model-1') will change. We can also here via the function argument also the step value 

We can watch also an application parameter – example app parameter  renderLevel:

 

 

//=============================================================
$scope.$watch('app.params.renderLevel', function (newValue, oldValue, scope) {
 // console.warn("called watch function with newValue=" +newValue+ " <=> oldValue was="+oldValue+ " <=> scope.renderLevel="+scope.renderLevel);
  //pay attention here is scope without $ !
   if(scope.renderLevel!= undefined) {
    //console.log('new value of renderLevel = '+newValue);
    scope.shaderUpdate(scope.renderLevel)
    $scope.$applyAsync();
  }
});

 

 

View solution in original post

9 REPLIES 9

Hello ES_9419715,

 

The solution might be to use CSS stylesheet to do fade in and fade out.

Please have a look to this post :

https://stackoverflow.com/questions/30125705/css-how-to-make-an-element-fade-in-and-then-fade-out

 

About the event, I would recommend to look in these posts in PTC Community :

https://community.ptc.com/t5/Vuforia-Studio-and-Chalk-Tech/List-of-Vuforia-Studio-events-which-we-could-be-used-as-listener/ta-p/613258

https://community.ptc.com/t5/Vuforia-Studio/Bind-a-Javascript-function-to-an-Application-Event/td-p/523304

 

Best regards,

Samuel

Hello @Ace_Rothstein ,

you can achieve this effect also with javascript. Here is an sample code which will work generally for widget which supports the opacity property e.g. 3D widgets modelItem, model or 3DImage etc. :

 

$scope.fadeOut = function(widget, time, interval) {
  let w = (widget.opacity !== undefined ? widget : $scope.view.wdg[widget]); //wiget name or widget it self
  if (time <= 0 || interval <= 0 || w.opacity === undefined) { throw "Cannot fade this widget"; }
  let steps = Math.floor(time / interval);
  let opDelta = w.opacity / steps;
  return $interval(() => w.opacity = (opDelta < w.opacity) ? (w.opacity - opDelta) : 0, interval, steps);
}

$scope.fadeIn = function(widget, targetOpacity,time, interval) {
  let w = (widget.opacity !== undefined ? widget : $scope.view.wdg[widget]);
  if (time <= 0 || interval <= 0 || w.opacity === undefined) { throw "Cannot fade this widget"; }
  let steps = Math.floor(time / interval);
  let opDelta = targetOpacity / steps;
  return $interval(() => w.opacity = (targetOpacity > w.opacity) ? (w.opacity + opDelta) : targetOpacity, interval, steps);
}

//call of the fadeOut for different widget with different time
$scope.testFadeOut= function()
{
  
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['modelItem-1'],2000,200) } ,500)
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['modelItem-2'],4000,200) } ,1500) 
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['modelItem-3'],6000,200) } ,2500)
$timeout( ()=>{$scope.fadeOut($scope.view.wdg['model-1']    ,5000,200) } ,3500)
}
/call of the fadeIn for different widget with different time
$scope.testFadeIn= function()
{
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['modelItem-1'],0.8,2000,200) } ,500)
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['modelItem-2'],0.9,4000,200) } ,1500)
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['modelItem-3'],1.0,6000,200) } ,2500)
  $timeout( ()=>{$scope.fadeIn($scope.view.wdg['model-1']     ,1.0,5000,200) } ,3500)
}

 

 

So this example will work where  it will  fade In or fade out different widgets (here modelItems and model) with different speed/time.

Here the arguments are

-the widget

-the time where the fade in/out should be completed,

-the interval step

-for fade in function the target opacity

Here when I tested it in a project:

 

2020-09-28_11-49-43.jpg

 

You can test it as mentioned for widget which supports the opacity property. The $timeout service was used to call the functions with some delay.

You mentioned "to trigger" in your question. I think one possible way to trigger a function call depending on value change is to use $watch construct. Example:

 

:

 

$scope.$watch('view.wdg["model-1"].currentStep', function(val) {
 //will call this function when the currentStep will chnage
if(val==2) $scope.testFadeOut();
if(val==4) $scope.testFadeIn();
    $scope.$applyAsync();
});

 

 

Here we will call the function when the value of  a widget property e.g. here currentStep (widget 'model-1') will change. We can also here via the function argument also the step value 

We can watch also an application parameter – example app parameter  renderLevel:

 

 

//=============================================================
$scope.$watch('app.params.renderLevel', function (newValue, oldValue, scope) {
 // console.warn("called watch function with newValue=" +newValue+ " <=> oldValue was="+oldValue+ " <=> scope.renderLevel="+scope.renderLevel);
  //pay attention here is scope without $ !
   if(scope.renderLevel!= undefined) {
    //console.log('new value of renderLevel = '+newValue);
    scope.shaderUpdate(scope.renderLevel)
    $scope.$applyAsync();
  }
});

 

 

Thanks a lot @RolandRaytchev ! Also is there a way to change the color of the font in a 3D Gauge after it achieves a certain value or after a particular time delay? Is there any Font attributes to change the font outline also.

Yes this is possible.

To change the text you can use e.g. watch and some code like :

 

 

$scope.$watch('view.wdg["3DGauge-1"].text', function(val) {
 //will call this function when the currentStep will chnage
if(parseFloat(val)>=50) { // suposing that the text contains a float value
    $scope.setWidgetProp("3DGauge-1","textattrs","fill:rgba(255, 0, 0,1);textbaseline:top;textalign:left");
    $scope.setWidgetProp("3DGauge-1","font","Courier");
    $scope.setWidgetProp("3DGauge-1","fontsize","60px");}
else {
      $scope.setWidgetProp("3DGauge-1","textattrs","fill:rgba(0, 255, 255, 1);textbaseline:middle;textalign:center");
     $scope.setWidgetProp("3DGauge-1","font","Arial");
     $scope.setWidgetProp("3DGauge-1","fontsize","30px");
    };
    $scope.$applyAsync();
});

 

 

2021-03-15_12-30-56.gif

 

Antoher option is  to use a style definition from Thingworx , so far I know  it should work for  3DGauge

 

To change the values and to change back after some  delays - the simple way is to use some construct like this:

 

$scope.myFunction= function()
{
var delay1=3000;// 3 secs
var delay2= 60000;// 6seconds
$timeout(()=>{ 
$scope.setWidgetProp("3DGauge-1","textattrs","fill:rgba(0, 255, 255, 1);textbaseline:middle;textalign:center");
   $scope.setWidgetProp("3DGauge-1","font","Arial");
   $scope.setWidgetProp("3DGauge-1","fontsize","30px");
  $scope.$applyAsync();
},delay1); // this will  call the first setting after delay1-> here 3 sec

$timeout(()=>{ 
$scope.setWidgetProp("3DGauge-1","textattrs","fill:rgba(255, 0, 0, 1);textbaseline:top;textalign:left");
    $scope.setWidgetProp("3DGauge-1","font","Courier");
   $scope.setWidgetProp("3DGauge-1","fontsize","60px");
  $scope.$applyAsync();
},delay2); // this will call the second setting after delay2 -delay1 
//after first call 3 sec and 6 sec after call of myFunction
};

 

 

Any idea about changing the font outline too? It appears that the font outline of the text in 3D gauges is white by default. It doesn't give a smooth transition effect unless the font outline changes too.

to have  an  apperance of the text outline like in this picture:

2021-03-29_13-15-56.jpg

some code like this:

 $scope.setWidgetProp("3DGauge-1","textattrs","fill:rgba(0, 0, 255, 1);textbaseline:top;textalign:left;font-size: 40px;stroke:green;colostroke-width: 3px;");
$scope.setWidgetProp("3DGauge-1","font","Arial");
$scope.setWidgetProp("3DGauge-1","fontsize","30px");

and to have  an  apperance of the text outline like in the second picture:

2021-03-29_13-16-07.jpg

some code like this:

  $scope.setWidgetProp("3DGauge-1","textattrs","fill:rgba(255, 0, 0, 1);textbaseline:top;textalign:left;font-size: 40px;stroke:black;colostroke-width: 3px");
    $scope.setWidgetProp("3DGauge-1","font","Courier");
   $scope.setWidgetProp("3DGauge-1","fontsize","60px");

 

Works as expected. Thanks @RolandRaytchev . 

@RolandRaytchev 

 

Thanks for the tips!

But still I have a question.

 

3D Gauge Widget Text properties could be controlled by textattrs.

But how to proceed the same modification to a 3D Label Widget?

let theColor = 'rgba(' + R + ',' + G + ',' + B + ',1);';        
$scope.setWidgetProp("3DLabel-1", "fontColor", theColor)
$scope.setWidgetProp("3DGauge-1","textattrs","fill:" + theColor + "textbaseline:middle;textalign:center;font-size: 40px;stroke:white;colostroke-width: 3px;");

The code above modify the Text Color of 3D Gauge Widget Text, but does nothing to 3D Label Widget Text.

What to resolve the issue?

 

Thanks in advance.

Hi @dsgnrClarK ,

 

yes , this is a good question. In fact I needed some tests to find out the difference here. I think this is a point what depends on the internal implementation of the widget.

So , what I believe (not 100% but seem to work) is that the Text appearance attribute on the toggle does not follow a CSS definition (also there is not explicit class attribute for this widget) but it use the SVG attributes according to the SVG attribute reference

https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute

e.g.

https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/Fills_and_Strokes

The 3D label widget seem not to use the SVG attributes but it could be driven by the properties (Font Family Font Color, Font Outline Color and scale ) dr Also for the 3d Label you can use css style definition according to the Vuforia Studio Help : http://support.ptc.com/help/vuforia/studio/en/#page/Studio_Help_Center%2FWidget3DLabel.html

So for example the class defintion in the STYLES >Applicaiton :

 

.ptc-3DLabel {  
  	font-family: Century Gothic;
  	color: black;
  	--text-stroke-color: yellow;
  	--text-stroke-width: 3px; /*csslint ignore*/
  	font-weight: normal;
  	font-style: italic;
  	background-color: grey;
}

 

will change the apperance of the 3DLabel to :

 

 

2021-04-06_12-27-12.jpg

Top Tags