Stop GIF Animation in WebView of UWP - animation

I am using a webview in my UWP application where a gif image will be provided from external web. There is a requirement that, I need to stop the GIF animation after staying 5 seconds on the page. How can I accomplish this??? I was looking for injecting Java Script, but couldn't find out the actual way . Can anyone help please???

For this scenario, a common workaround is to use InvokeScriptAsync with the JavaScript eval function to use the HTML event handlers
For stopping Gif, you could use the following javascript method.
[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);
function is_gif_image(i) {
return /^(?!data:).*\.gif/i.test(i.src);
}
function freeze_gif(i) {
var c = document.createElement('canvas');
var w = c.width = i.width;
var h = c.height = i.height;
c.getContext('2d').drawImage(i, 0, 0, w, h);
try {
i.src = c.toDataURL("image/gif");
} catch (e) {
for (var j = 0, a; a = i.attributes[j]; j++)
c.setAttribute(a.name, a.value);
i.parentNode.replaceChild(c, i);
}
}
And inject it with the eval function 5 seconds after the page is Navigation Completed.
private async void MyWebView_NavigationCompleted(WebView sender, WebViewNavigationCompletedEventArgs args)
{
await Task.Delay(TimeSpan.FromSeconds(5));
var function = #"[].slice.apply(document.images).filter(is_gif_image).map(freeze_gif);
function is_gif_image(i) {
return /^(?!data:).*\.gif/i.test(i.src);
}
function freeze_gif(i) {
var c = document.createElement('canvas');
var w = c.width = i.width;
var h = c.height = i.height;
c.getContext('2d').drawImage(i, 0, 0, w, h);
try {
i.src = c.toDataURL('image / gif');
} catch (e) { // cross-domain -- mimic original with all its tag attributes
for (var j = 0, a; a = i.attributes[j]; j++)
c.setAttribute(a.name, a.value);
i.parentNode.replaceChild(c, i);
}}";
await MyWebView.InvokeScriptAsync("eval", new string[] { function });
}

Related

Xamarin.Forms ZXing BarcodeReaderGeneric returns null when scanning an image in the gallery

I am developing a barcode reader with Xamarin.Forms. And I'm trying to scan the image on Android device.
First I select the image from the gallery with Xamarin.Essentials MediaPicker and from the path of this image I get an RGBLuminance with the Dependency class.
Then I am trying to decode this RGBLuminance with the Decode() method of the ZXing BarcodeReaderGeneric class. However, the result always returns null.
It is my demo project : https://onedrive.live.com/?authkey=%21AFLjjM91wgZkBGU&cid=58BE2C2C3447FFA2&id=58BE2C2C3447FFA2%219829&parId=root&action=locate
Command in the ViewModel class:
public ICommand PickCommand => new Command(PickImage);
private async void PickImage()
{
var pickResult = await MediaPicker.PickPhotoAsync(new MediaPickerOptions
{
Title = "Select a barcode."
});
var path = pickResult.FullPath;
var RGBLuminance = DependencyService.Get<ILuminance>().GetRGBLuminanceSource(path);
var reader = new BarcodeReaderGeneric();
var result = reader.Decode(RGBLuminance); // result always null.
}
Method of Dependency class in Android:
public RGBLuminanceSource GetRGBLuminanceSource(string imagePath)
{
if (File.Exists(imagePath))
{
Android.Graphics.Bitmap bitmap = BitmapFactory.DecodeFile(imagePath);
List<byte> rgbBytesList = new List<byte>();
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
var c = new Android.Graphics.Color(bitmap.GetPixel(x, y));
rgbBytesList.AddRange(new[] { c.A, c.R, c.G, c.B });
}
}
byte[] rgbBytes = rgbBytesList.ToArray();
return new RGBLuminanceSource(rgbBytes, bitmap.Height, bitmap.Width, RGBLuminanceSource.BitmapFormat.RGB32);
}
return null;
}
You should change the line
return new RGBLuminanceSource(rgbBytes, bitmap.Height, bitmap.Width, RGBLuminanceSource.BitmapFormat.RGB32);
to
return new RGBLuminanceSource(rgbBytes, bitmap.Width, bitmap.Height, RGBLuminanceSource.BitmapFormat.RGB32);
And to be more accurate with the RGB format you should
change RGBLuminanceSource.BitmapFormat.RGB32 to RGBLuminanceSource.BitmapFormat.ARGB32
or change rgbBytesList.AddRange(new[] { c.A, c.R, c.G, c.B }); to rgbBytesList.AddRange(new[] { c.R, c.G, c.B, c.A });
Can you try with this pictures?
Picture One
Picture Two

How can I use round dots in my animated line in HTML5 canvas?

I am using line creation on HTML5 canvas to create two animated dashed paths, one after the other. I simply want to change the dashes to rounded dots.
I've seen setting context lineCap ='round', etc but it doesn't work
var canvas;
var ctx;
var pathColor="black";
function Vector(x, y)
{
this.X = x;
this.Y = y;
}
var m1, c1;
var pCount1=0;
var pCount2=0;
var pathInt = null;
var points1 = [new Vector(1400, 1500),new Vector(1365, 1495),new Vector(1330, 1490),new Vector(1295, 1485),new Vector(1260, 1480)];
var points2 = [new Vector(1280, 480),new Vector(1195, 470),new Vector(1110, 460),new Vector(1080, 450),new Vector(1000, 240),new Vector(1300, 140),new Vector(1580, 140),new Vector(1590, 180),];
function getClr() {
if(pathColor=="lightgrey") {
pathColor="black";
}
else {
pathColor="lightgrey";
}
}
window.onload = function()
{
m1 = document.querySelector("#b");
c1 = m1.getContext("2d");
pathInt = setInterval(function(){ pathTo(); }, 250);
};
function pathTo()
{
if(pCount1 <= points1.length && points1.length!=0)
{
c1.strokeStyle = pathColor;
c1.lineWidth = 15;
c1.setLineDash([25, 10]);
c1.beginPath();
c1.moveTo(points1[0].X, points1[0].Y);
for(var i = 0; i < pCount1; i++)
{
c1.lineTo(points1[i].X, points1[i].Y);
}
pCount1++;
c1.stroke();
}
else if(pCount2 <= points2.length && points2.length!=0)
{
c1.strokeStyle = pathColor;
c1.lineWidth = 15;
c1.setLineDash([25, 10]);
c1.beginPath();
c1.moveTo(points2[0].X, points2[0].Y);
for(var i = 1; i < pCount2; i++)
{
c1.lineTo(points2[i].X, points2[i].Y);
}
pCount2++;
c1.stroke();
pCount2++;
}
else {
clearInterval(pathInt);
setTimeout(function(){ redoPath(); }, 5000);
}
}
function redoPath() {
pCount1=0;
pCount2=0;
//c1.clearRect(0, 0, m1.width, m1.height);
getClr();
pathInt = setInterval(function(){ pathTo(); }, 250);
}
<canvas id="b" width="1746" height="1746" style="position:absolute;top:100px;left:50px;z-index:100;">
</canvas>
I know this must be possible, ..but not sure which properties I need to change. Any help is appreciated.

Cocos Creator js animate sprite

I have animated a sprite using a sprite sheet and the update function,
like so:
Note: I have dragged the plist into the atlas field of the sprite node (the same node the monster.js script is attached to) in the Ccos Creator UI.
//monster.js
onLoad: function(){
// change monsters face
this.faces['1'] = 'monster1';
this.faces['2'] = 'monster2';
this.faces['3'] = 'Rmonster1';
this.faces['4'] = 'Rmonster2';
}
update: function (dt) {
this.timekeep += dt;
if(this.timekeep > 0.1){
var self = this;
cc.loader.loadRes('monsters', cc.SpriteAtlas, function (err, atlas) {
self.getComponent(cc.Sprite).spriteFrame = atlas.getSpriteFrame(self.faces[self.monstersN]);
});
this.timekeep = 0;
this.monstersN++;
if(this.monstersN > 4){
this.monstersN = 1;
}
}
It actually works fine. I have already thought I should export the cc.loader.loaderRes into the onLoad function and save the atlas as a global var instead of loading every time the update is called.
However…seeing that there are built in animation functions, this can’t be the correct solution. So I tried this:
onLoad: function () {
// change monster face
this.faces['1'] = 'monster1';
this.faces['2'] = 'monster2';
this.faces['3'] = 'Rmonster1';
this.faces['4'] = 'Rmonster2';
var self = this;
cc.loader.loadRes('monsters', cc.SpriteAtlas, function (err, atlas) {
var sprite = self.getComponent(cc.Sprite);
var animFrames = [];
for (var i = 1; i < 4; i++) {
var spriteFrame = atlas.getSpriteFrame(self.faces[i]);
var animFrame = new cc.AnimationFrame();
animFrame.initWithSpriteFrame(spriteFrame, 1, null);
animFrames.push(animFrame);
}
var animation = sprite.Animation.create(animFrames, 0.2, 100);
var animate = sprite.Animate.create(animation);
sprite.runAction(animate);
});
},
I get this error:
cc.AnimationFrame is not a constructor
So then I tried this:
onLoad: function () {
// change monster face
this.faces['1'] = 'monster1';
this.faces['2'] = 'monster2';
this.faces['3'] = 'Rmonster1';
this.faces['4'] = 'Rmonster2';
var self = this;
cc.loader.loadRes('monsters', cc.SpriteAtlas, function (err, atlas) {
self.atlasA = atlas;
});
var sprite = this.getComponent(cc.Sprite);
var animFrames = [];
for (var i = 1; i < 4; i++) {
var spriteFrame = this.atlasA.getSpriteFrame(this.faces[i]);
var animFrame = new cc.AnimationFrame();
animFrame.initWithSpriteFrame(spriteFrame, 1, null);
animFrames.push(animFrame);
}
var animation = sprite.Animation.create(animFrames, 0.2, 100);
var animate = sprite.Animate.create(animation);
sprite.runAction(animate);
},
I get this error:
Cannot read property ‘getSpriteFrame’ of undefined
How can I use cc.animate to change the sprite using the spritesheet I have. All I want to achieve is to move through the plist in the order the images are in the plist, repeated until the monster is put back into the pool it came from.
Here is the solution for anyone who may still be looking.....
cc.AnimationClip.createWithSpriteFrames([sf1, sf2, ...], fps)

Delete specific image from loader

I have three images all from the same loader on screen. I need to delete a specific (targeted) bitmap once clicked. I have an onClick function below, any help is greatly appreciated. Thanks!
var nb_images:int = 3;
var bmp:Bitmap = new Bitmap;
var img_margin:int = stage.stageHeight/3.5;
var img_request:URLRequest;
var img_loader:Loader;
var images_container:Sprite = new Sprite();
addChild(images_container);
function remove_all_images():void {
for (var i:int = images_container.numChildren - 1; i >= 0; i--) {
images_container.removeChildAt(i);
}
}
function load_images():void {
remove_all_images();
for (var i:int = 0; i < nb_images; i++) {
img_request = new URLRequest('../img/planet' + (int(nb_images * Math.random())) + '.png');
img_loader = new Loader();
img_loader.load(img_request);
img_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, on_img_loaded);
}
}
function on_img_loaded(e:Event):void {
e.currentTarget.removeEventListener(Event.COMPLETE, on_img_loaded);
bmp = e.currentTarget.content;
bmp.x = 600, bmp.width = bmp.height = 80;
bmp.y = images_container.numChildren * (bmp.height + img_margin);
images_container.addChild(bmp);
stage.addEventListener(MouseEvent.CLICK, onClick);
function onClick(event:MouseEvent):void {
removeChild(e.target);
}
}
load_images();
Okay, first thing I did here was remove var bmp:Bitmap = new Bitmap. You're creating a reference you don't really need, so let's get rid of that altogether.
Now, in your on_img_loaded method, you're going to want to create a new Bitmap for each loaded image.
var bmp:Bitmap = e.currentTarget.content;
Then, you'll need to add the event listener directly to an InteractiveObject rather than the stage. Bitmaps are not InteractiveObjects, so we'll need to wrap it in something else before adding the listener.
var sprite: Sprite = new Sprite();
sprite.addChild(bmp);
addChild(sprite);
sprite.addEventListener(MouseEvent.CLICK, onClick);
Finally, create a method to remove the clicked Bitmap from images_container (note here I removed the nested function - this prevents argument ambiguity and is generally good practice).
function onClick(e:MouseEvent):void
{
images_container.removeChild(e.currentTarget);
}
This is the relevant code in its entirety (untested).
//remove var bmp:Bitmap = new Bitmap from the beginning of the code
function on_img_loaded(e:Event):void {
e.currentTarget.removeEventListener(Event.COMPLETE, on_img_loaded);
var bmp:Bitmap = e.currentTarget.content;
bmp.x = 600, bmp.width = bmp.height = 80;
bmp.y = images_container.numChildren * (bmp.height + img_margin);
var sprite: Sprite = new Sprite();
sprite.addChild(bmp);
addChild(sprite);
images_container.addChild(sprite);
sprite.addEventListener(MouseEvent.CLICK, onClick);
}
function onClick(e:MouseEvent):void
{
e.currentTarget.removeEventListener(MouseEvent.CLICK, onClick)
images_container.removeChild(e.currentTarget as DisplayObject);
}
Hope this helps!

Flash AS2 - grouping enemies

So I have a Flash ActionScript 2 code, which creates a preset amount of enemies, gives enemies stats, and makes them move around randomly. Code:
//Settings
var mapWidth:Number = 550;
var mapHeight:Number = 400;
var enemiesArray:Array = new Array();
var totalEnemies:Number;
var eClip:MovieClip;
//Math functions
function getdistance(x, y, x1, y1)
{
run = x1-x;
rise = y1-y;
return (hyp(run, rise));
}
function hyp(a, b)
{
return (Math.sqrt(a*a+b*b));
}
function resetDirection(mc:MovieClip)
{
mc.roamTime = random(50);
mc.t = mc.roamTime;
mc.roamDistance = random(60)+25;
mc.randomRoamDistanceX = (Math.random()*mc.roamDistance)+mc.xx-(mc.roamDistance/2);
mc.randomRoamDistanceY = (Math.random()*mc.roamDistance)+mc.yy-(mc.roamDistance/2);
mc.newRoamDistance = getdistance(mc._x, mc._y, mc.randomRoamDistanceX, mc.randomRoamDistanceY);
mc.norm = mc.roamSpeed/mc.newRoamDistance;
mc.finalRoamDistanceX = (mc.randomRoamDistanceX-mc.xx)*mc.norm;
mc.finalRoamDistanceY = (mc.randomRoamDistanceY-mc.yy)*mc.norm;
}
//function to move enemies
function moveIt(mc:MovieClip)
{
//reduce roamTime;
mc.t--;
//move enemy to new position
if (getdistance(mc._x, mc._y, mc.randomRoamDistanceX, mc.randomRoamDistanceY)>mc.roamSpeed) {
mc._x += mc.finalRoamDistanceX;
mc._y += mc.finalRoamDistanceY;
}
//rotate enemy
XXXdiff = mc.xx-mc.randomRoamDistanceX;
YYYdiff = -(mc.yy-mc.randomRoamDistanceY);
rrradAngle = Math.atan(YYYdiff/XXXdiff);
if (XXXdiff<0) {
cccorrFactor = 270;
} else {
cccorrFactor = 90;
}
//
mc.ship_mc._rotation = -(rrradAngle*360/(2*Math.PI)+cccorrFactor);
//check if time to reset, based on roamTime
if (mc.t<=0) {
resetDirection(mc);
}
}
//
// Generate Enemies
//
// set and save enemy stats
//
//
// createEnemies(number of enemies you want, movieclip where you want to create the enemies);
//
function createEnemies(amount:Number, targetLocation:MovieClip) {
trace("createEnemies: "+amount);
for (var i = 0; i<amount; i++) {
randomXpos = Math.round(Math.random()*mapWidth);
randomYpos = Math.round(Math.random()*mapHeight);
//add new enemy to map
var newEnemy:MovieClip = targetLocation.attachMovie("enemy1", "enemy1_"+i, targetLocation.getNextHighestDepth());
enemiesArray.push(newEnemy);
//
//set enemy stats
newEnemy.id = i;
newEnemy._x = randomXpos;
newEnemy._y = randomYpos;
//save x and y position
newEnemy.xx = newEnemy._x;
newEnemy.yy = newEnemy._y;
//
newEnemy.roamSpeed = 2
newEnemy.roamTime = random(50);
newEnemy.roamDistance = random(60)+25;
newEnemy.t = 0;
//
newEnemy.myHealth = 10;
newEnemy.myName = "Small Scout";
//
resetDirection(newEnemy);
//target enemy
newEnemy.onPress = function() {
trace("Enemy: "+this.tName+" "+this.id);
target_txt.text = this.myName+": "+this.id+" Health: "+this.myHealth;
};
newEnemy.onEnterFrame = function() {
moveIt(this);
};
}
}
start_btn.onRelease = function() {
if (start_txt.text == "Start") {
//run the create enemies function to start the engine
createEnemies(box_mc.numberOfEnemies.text, map_mc);
//hide start button
start_txt._visible =false;
this._visible = false;
box_mc._visible = false;
}
};
I want program enemies to be grouped (based on fireflies algorithm). My idea is write for loop to define attractiveness, but I don't know how to make my objects move to the most attractiveness. Maybe someone would help me with this problem?
I change this line:
newEnemy.myHealth = 10;
on this
newEnemy.myHealth = Math.round(random(9)+1);
myHealth would be responsible for attractiveness. I try to use code from this site and modificate code to let objects with low attractiveness follow objects with large attractiveness. Also, I want to stop algorith, when they are in the groups.

Resources