this could be an obvious question/answer but I am trying to host this AR-based example model website on my local XAMPP host but it keeps appearing with a white page.
Does this mean I cannot use the webcam on localhost or is my code incorrect? I have tried updating my XAMPP and trying with other AR models but nothing works. I have also tried using AMPPS instead of XAMPP but nothing works!
Any suggestions welcomed? Does XAMPP even work with AR models? Is there another localhost I could try for AR model.
<!DOCTYPE html>
<head>
<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
<!-- include three.js library -->
<script src='../../js/three.js'></script>
<script src='../../js/OBJLoader.js'></script>
<script src='../../js/MTLLoader.js'></script>
<!-- include jsartookit -->
<script src="../../jsartoolkit5/artoolkit.min.js"></script>
<script src="../../jsartoolkit5/artoolkit.api.js"></script>
<!-- include threex.artoolkit -->
<script src="../../threex/threex-artoolkitsource.js"></script>
<script src="../../threex/threex-artoolkitcontext.js"></script>
<script src="../../threex/threex-arbasecontrols.js"></script>
<script src="../../threex/threex-armarkercontrols.js"></script>
</head>
<script>
var scene, camera, renderer, clock, deltaTime, totalTime;
var arToolkitSource, arToolkitContext;
var markerRoot1;
var mesh0, mesh1;
initialize();
animate();
function initialize(){
scene = new THREE.Scene();
let ambientLight = new THREE.AmbientLight( 0xcccccc, 1.0 );
scene.add( ambientLight );
camera = new THREE.Camera();
scene.add(camera);
renderer = new THREE.WebGLRenderer({
antialias : true,
alpha: true
});
renderer.setClearColor(new THREE.Color('lightgrey'), 0)
renderer.setSize( 640, 480 );
renderer.domElement.style.position = 'absolute'
renderer.domElement.style.top = '0px'
renderer.domElement.style.left = '0px'
document.body.appendChild( renderer.domElement );
clock = new THREE.Clock();
deltaTime = 0;
totalTime = 0;
arToolkitSource = new THREEx.ArToolkitSource({
sourceType : 'webcam',
});
function onResize(){
arToolkitSource.onResize()
arToolkitSource.copySizeTo(renderer.domElement)
if ( arToolkitContext.arController !== null )
{
arToolkitSource.copySizeTo(arToolkitContext.arController.canvas)
}
}
arToolkitSource.init(function onReady(){
onResize()
});
window.addEventListener('resize', function(){
onResize()
});
arToolkitContext = new THREEx.ArToolkitContext({
cameraParametersUrl: '../../data/camera_para.dat',
detectionMode: 'mono'
});
arToolkitContext.init( function onCompleted(){
camera.projectionMatrix.copy( arToolkitContext.getProjectionMatrix() );
});
markerRoot1 = new THREE.Group();
scene.add(markerRoot1);
let markerControls1 = new THREEx.ArMarkerControls(arToolkitContext, markerRoot1, {
type: 'pattern', patternUrl: "../../data/hiro.patt",
})
let geometry1 = new THREE.PlaneBufferGeometry(1,1, 4,4);
let loader = new THREE.TextureLoader();
let texture = loader.load( '../../images/grass.jpg', render );
let material1 = new THREE.MeshBasicMaterial( { map: texture } );
mesh1 = new THREE.Mesh( geometry1, material1 );
mesh1.rotation.x = -Math.PI/2;
markerRoot1.add( mesh1 );
new THREE.MTLLoader()
.setPath( '../../models/puppy/' )
.load( 'puppy.mtl', function ( materials ) {
materials.preload();
new THREE.OBJLoader()
.setMaterials( materials )
.setPath( '../../models/puppy/' )
.load( 'puppy.obj', function ( group ) {
mesh0 = group.children[0];
mesh0.material.side = THREE.DoubleSide;
mesh0.position.y = 0.025;
mesh0.scale.set(1.25,1.25,1.25);
mesh0.rotation.y = Math.PI / 2;
markerRoot1.add(mesh0);
}, onProgress, onError );
});
function onProgress(xhr) { console.log( (xhr.loaded / xhr.total * 100) + '% loaded' ); }
function onError(xhr) { console.log( 'An error happened' ); }
}
function update(){
if ( arToolkitSource.ready !== false )
arToolkitContext.update( arToolkitSource.domElement );
}
function render(){
renderer.render( scene, camera );
}
function animate(){
requestAnimationFrame(animate);
deltaTime = clock.getDelta();
totalTime += deltaTime;
update();
render();
}
</script>
</body>
</html>
Related
I am building a small website with three.js (I am a absolute beginner). My website is working fine but I want to remove a obj from the scene. How can I do this?
What I want is that when I click a button, the OBJ disappears. How can I do this?
My code:
<script async src="https://unpkg.com/es-module-shims#1.3.6/dist/es-module-shims.js"></script>
<script type="importmap">
{
"imports": {
"three": "https://unpkg.com/three#0.149.0/build/three.module.js",
"three/addons/": "https://unpkg.com/three#0.149.0/examples/jsm/"
}
}
</script>
<script type="module">
import * as THREE from 'three';
import { OrbitControls } from 'three/addons/controls/OrbitControls.js';
import { OBJLoader } from 'three/addons/loaders/OBJLoader.js';
import { GUI } from 'three/addons/libs/lil-gui.module.min.js';
const scene = new THREE.Scene();
const renderer = new THREE.WebGLRenderer({ antialias: true });;
const camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 1000 );
const controls = new OrbitControls( camera, renderer.domElement );
const loader = new OBJLoader();
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
camera.position.z = 20;
camera.position.y = 20;
const light = new THREE.SpotLight()
light.position.set(10, 5, 5)
scene.add(light)
function loadtavel(){
loader.load(
// resource URL
'assets/objtest.obj',
// called when resource is loaded
function ( object ) {
scene.add( object );
// object.translateZ( 10 );
},
// called when loading is in progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
}
loader.load(
// resource URL
'assets/untitled.obj',
// called when resource is loaded
function ( object ) {
scene.add( object );
object.translateY( 10 );
},
// called when loading is in progresses
function ( xhr ) {
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
// called when loading has errors
function ( error ) {
console.log( 'An error happened' );
}
);
renderer.setClearColor( 0xffffff, 0);
function removeLoad(){
}
// renderer.physicallyCorrectLights = true
// renderer.shadowMap.enabled = true
renderer.outputEncoding = THREE.sRGBEncoding
// texture.encoding = THREE.sRGBEncoding;
var obj = {
add: function() {
loadtavel();
}
};
var obj2 = {
add: function() {
removeLoad()
}
};
function animate() {
requestAnimationFrame( animate );
// cube.rotation.x += 0.01;
// cube.rotation.y += 0.01;
renderer.render( scene, camera );
};
animate();
const gui = new GUI()
const cubeFolder = gui.addFolder('Cube')
cubeFolder.add(obj, 'add').name('Load!');
cubeFolder.add(obj2, 'add').name('Unload!');
cubeFolder.open()
</script>
</html>
I already searched for a solution but I couldn't find anything
If you want to make the OBJ disappear, you could just change its visibility:
obj.visibility = false;
If you want to remove it from the scene, just do so with:
scene.remove(obj);
On my UI where I have open source project,
https://github.com/townsean/canvas-pixel-color-counter
so what I am trying to do is :-
I want to export HTML data into excel,all input div count data, earlier I was using exporting to excel plugin but it is only exporting the HTML table data not input fields data
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<meta name="author" content="Ashley G">
<meta name="description" content="A web app that counts the number of pixels in an image per a unique color.">
<title>Pixel Color Counter</title>
<link rel="shortcut icon" href="./assets/favicon.ico" type="image/x-icon">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link href="https://fonts.googleapis.com/css?family=Press+Start+2P&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Open+Sans&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
<button onclick="exportTableToExcel('tblData')">Export Table Data To Excel File</button>
</head>
<body>
<header>
<h1>Pixel Color Counter</h1>
</header>
<main>
<!-- About Section -->
<section id="about">
<h2>Count Pixels by Color</h2>
<p>Pixel Color Counter is vanilla JS web application that accepts an image file (selected by the user) and displays the total number of pixels per a unique color. </p>
</section>
<!-- Upload Image Section -->
<section id="upload-container">
<h2>Upload an Image</h2>
<div>
<label for="image">Choose an image:</label>
<input type="file" id="image" name="image" accept="image/png, image/jpeg">
</div>
<canvas id="canvas"></canvas>
</section>
<!-- Pixel Color Swatches and Count -->
<section id="pixel-count-container" class="pixel-count-container invisible">
<h2>Pixel Counts by Color</h2>
<p><span id="color-count"></span> unique colors</p>
<div id="color-swatches" class="color-swatches">
</div>
</section>
</main>
<div id="wait-indicator" class="invisible">
<img src="assets/ashley_sprite.gif">
<p>Please Wait</p>
</div>
<footer>
Copyright © 2019 Ashley Grenon
</footer>
<script src="counter.js"></script>
<script src="main.js"></script>
</body>
</html>
and jquery
and counter js this project
// https://developer.mozilla.org/en-US/docs/Tools/Performance/Scenarios/Intensive_JavaScript
self.addEventListener("message", go);
/**
*
*/
function go(message) {
const imageData = message.data.imageData;
const colorCounts = countPixels(imageData);
self.postMessage({
"command": "done",
colorCounts
});
}
/**
* Counts the number of pixels per a unique color
* https://stackoverflow.com/questions/19499500/canvas-getimagedata-for-optimal-performance-to-pull-out-all-data-or-one-at-a
*/
function countPixels(data) {
const colorCounts = {};
for(let index = 0; index < data.length; index += 4) {
const rgba = `rgba(${data[index]}, ${data[index + 1]}, ${data[index + 2]}, ${(data[index + 3] / 255)})`;
if (rgba in colorCounts) {
colorCounts[rgba] += 1;
} else {
colorCounts[rgba] = 1;
}
}
return colorCounts;
}
and main.js
// To avoid Uncaught DOMException while using Web Workers
// Run python -m http.server 8000
// https://stackoverflow.com/questions/8170431/using-web-workers-for-drawing-using-native-canvas-functions
const worker = new Worker('./counter.js');
handleWorkerCompletion = (message) => {
if(message.data.command == "done") {
// draw color swatches
this.drawColorSwatch(message.data.colorCounts);
worker.removeEventListener("message", handleWorkerCompletion);
// hide wait indicator
const waitIndicator = document.getElementById("wait-indicator");
waitIndicator.classList.add("invisible");
waitIndicator.classList.remove("fadein");
// scroll to color swatch section
const pixelCountContainer = document.getElementById('pixel-count-container');
pixelCountContainer.scrollIntoView({ behavior: 'smooth'});
const colorCountLabel = document.getElementById('color-count');
colorCountLabel.innerText = Object.keys(message.data.colorCounts).length;
}
};
/**
* Event listener for when the file upload has been updated
*/
document.getElementById("image").addEventListener('change', (e) => {
this.loadImage(e.target.files[0]);
}, false);
/**
* Given a valid image file, load the image into the canvas
* Good explantation the the image data: https://css-tricks.com/manipulating-pixels-using-canvas/#article-header-id-1
*/
loadImage = (file) => {
const url = window.URL.createObjectURL(file);
const img = new Image();
img.src = url;
img.onload = () => {
this.reset();
const canvas = document.getElementById('canvas');
canvas.width = img.width;
canvas.height = img.height;
const context = canvas.getContext('2d');
context.drawImage(img, 0, 0);
const uploadContainer = document.getElementById('upload-container');
uploadContainer.appendChild(img);
const imageData = context.getImageData(0, 0, canvas.width, canvas.height);
window.URL.revokeObjectURL(this.src);
worker.addEventListener("message", handleWorkerCompletion, false);
worker.postMessage({
"imageData": imageData.data
});
const waitIndicator = document.getElementById("wait-indicator");
waitIndicator.classList.remove("invisible");
waitIndicator.classList.add("fadein");
}
};
/**
*
*/
drawColorSwatch = (colorCount) => {
let colorSwatches = document.getElementById('color-swatches');
for(const color in colorCount) {
const container = document.createElement("section");
const swatch = document.createElement("div");
const colorCountLabel = document.createElement("span");
container.classList.add("color-swatch-container");
swatch.classList.add("color-swatch");
swatch.style.background = color;
swatch.title = color;
colorCountLabel.innerHTML = `: ${colorCount[color]}`;
container.appendChild(swatch);
container.appendChild(colorCountLabel);
colorSwatches.appendChild(container);
}
let pixelCountContainer = document.getElementById('pixel-count-container');
pixelCountContainer.classList.remove('invisible');
};
/**
* Clear DOM of past color counting
*/
reset = () => {
let pixelCountContainer = document.getElementById('pixel-count-container');
pixelCountContainer.classList.add('invisible');
let colorSwatches = document.getElementById('color-swatches');
while (colorSwatches.firstChild) {
colorSwatches.removeChild(colorSwatches.firstChild);
}
let uploadContainer = document.getElementById('upload-container');
let image = uploadContainer.getElementsByTagName('img')[0];
if (image) {
uploadContainer.removeChild(image);
}
const canvas = document.getElementById('canvas');
const context = canvas.getContext('2d');
context.clearRect(0, 0, canvas.width, canvas.height);
}
function exportTableToExcel(color-swatches, filename = ''){
var downloadLink;
var dataType = 'application/vnd.ms-excel';
var tableSelect = document.getElementById(color-swatches);
var tableHTML = tableSelect.outerHTML.replace(/ /g, '%20');
// Specify file name
filename = filename?filename+'.xls':'excel_data.xls';
// Create download link element
downloadLink = document.createElement("a");
document.body.appendChild(downloadLink);
if(navigator.msSaveOrOpenBlob){
var blob = new Blob(['\ufeff', tableHTML], {
type: dataType
});
navigator.msSaveOrOpenBlob( blob, filename);
}else{
// Create a link to the file
downloadLink.href = 'data:' + dataType + ', ' + tableHTML;
// Setting the file name
downloadLink.download = filename;
//triggering the function
downloadLink.click();
}
}
I have been displaying data attached to a few nodes in the viewer using a custom docking panel. I have attached the listener event on the click of those nodes and instantiating a new docking panel instance.
It works fine. New custom panel get's displayed every time I click on a node. There is a close handler attached to the close button which closes the panel.
But, how can I close the existing panel before opening a new one? I tried to initialize the viewer with initializeCloseHandler so that wherever clicked the opened docking panel closes. But it's not working. I am unable to get the viewer instance there.
Now both instances get added one above another. I am attaching a screenshot of it for reference - https://i.stack.imgur.com/lT5Y1.png
How can I achieve this? This is what I have tried so far,
Sample code:
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
<meta charset="utf-8">
<link rel="stylesheet" href="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/style.min.css" type="text/css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://developer.api.autodesk.com/modelderivative/v2/viewers/7.*/viewer3D.min.js"></script>
<style>
body {
margin: 0;
}
#forgeViewer {
width: 100%;
height: 100%;
margin: 0;
background-color: #F0F8FF;
}
</style>
</head>
<body>
<div id="forgeViewer"></div>
</body>
<script>
var viewer;
var options = {
env: 'AutodeskProduction',
api: 'derivativeV2', // for models uploaded to EMEA change this option to 'derivativeV2_EU'
getAccessToken: function(onTokenReady) {
var token = 'access token here';
var timeInSeconds = 3600; // Use value provided by Forge Authentication (OAuth) API
onTokenReady(token, timeInSeconds);
}
};
SimplePanel = function(parentContainer, id, title, content, x, y)
{
this.content = content;
Autodesk.Viewing.UI.DockingPanel.call(this, parentContainer, id, title,{shadow:false});
// Auto-fit to the content and don't allow resize. Position at the coordinates given.
//
this.container.style.height = "250px";
this.container.style.width = "450px";
this.container.style.resize = "auto";
this.container.style.left = x + "px";
this.container.style.top = y + "px";
this.container.style.zIndex = 2;
};
SimplePanel.prototype = Object.create(Autodesk.Viewing.UI.DockingPanel.prototype);
SimplePanel.prototype.constructor = SimplePanel;
SimplePanel.prototype.initialize = function()
{
this.title = this.createTitleBar(this.titleLabel || this.container.id);
this.container.appendChild(this.title);
this.container.appendChild(this.content);
this.initializeMoveHandlers(this.container);
this.closer = document.createElement("span");
this.closer = this.createCloseButton();
this.initializeCloseHandler(this.closer);
this.container.appendChild(this.closer);
var op = {left:false,heightAdjustment:45,marginTop:0};
this.scrollcontainer = this.createScrollContainer(op);
// console.log("id - "+viewer.model.getFragmentList().fragments.fragId2dbId);
console.log(viewer.getSelection());
var id = viewer.getSelection();
var dataItem;
var data = [
{
id:"2648",
name:"Chiller",
temp:"300 deg",
serviceReq:true,
reservations:"3"
},
{
id:"2228",
name:"Door",
temp:"150 deg",
serviceReq:false,
reservations:"4"
},
{
id:"2198",
name:"Cooler",
temp:"400 deg",
serviceReq:true,
reservations:"2"
}
]
data.forEach(item => {
if(item.id == id){
dataItem = item;
}
})
var html = [
'<div class="uicomponent-panel-controls-container">',
'<div class="panel panel-default">',
'<table class="table table-hover table-responsive" id = "clashresultstable">',
'<thead>',
'<th>Key</th><th>Value</th>',
'</thead>',
'<tbody>',
'<tr><td>ID</td><td>'+dataItem.id+'</td></tr>',
'<tr><td>Name</td><td>'+dataItem.name+'</td></tr>',
'<tr><td>Temperature</td><td>'+dataItem.temp+'</td></tr>',
'<tr><td>Service Requests</td><td>'+dataItem.serviceReq+'</td></tr>',
'<tr><td>Reservations</td><td>'+dataItem.reservations+'</td></tr>',
'</tbody>',
'</table>',
'</div>',
'</div>'
].join('\n');
$(this.scrollContainer).append(html);
this.initializeMoveHandlers(this.title);
};
Autodesk.Viewing.Initializer(options, function() {
var htmlDiv = document.getElementById('forgeViewer');
viewer = new Autodesk.Viewing.GuiViewer3D(htmlDiv);
var startedCode = viewer.start();
if (startedCode > 0) {
console.error('Failed to create a Viewer: WebGL not supported.');
return;
}
console.log('Initialization complete, loading a model next...');
});
var documentId = 'urn:(urn)';
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
function onDocumentLoadSuccess(viewerDocument) {
var defaultModel = viewerDocument.getRoot().getDefaultGeometry();
viewer.loadDocumentNode(viewerDocument, defaultModel);
viewer.addEventListener( Autodesk.Viewing.SELECTION_CHANGED_EVENT, event=>{
var content = document.createElement('div');
var mypanel = new SimplePanel(NOP_VIEWER.container,'mypanel','My Panel',content,20,20);
mypanel.setVisible(true);
})
}
// function closer(){ -- tried to attach this handler to the viewer instance,but didn't work
// SimplePanel.setVisible(false);
// }
function onDocumentLoadFailure() {
console.error('Failed fetching Forge manifest');
}
</script>
</html>````
[1]: https://i.stack.imgur.com/lT5Y1.png
I would advise you to use a viewer extension to manage your panel in order to reuse the same panel instance. Here are some examples for you:
https://github.com/yiskang/forge-au-sample/blob/master/properties/scripts/AdnPropsPanel.js
https://github.com/yiskang/forge-au-sample/blob/master/model-structure/scripts/AdnStructurePanel.js
If you don't want to implement an extension, you may store the mypanel variable somewhere, and use if statement to destroy the old panel before creating a new one.
var mypanel = null;
// Other code snippet
viewer.addEventListener( Autodesk.Viewing.SELECTION_CHANGED_EVENT, event=> {
if( mypanel != null ) {
//NOP_VIEWER.container.removeChild( mypanel.container );
mypanel.uninitialize();
mypanel = null;
}
var content = document.createElement('div');
mypanel = new SimplePanel(NOP_VIEWER.container,'mypanel','My Panel',content,20,20);
mypanel.setVisible( true );
})
Hope it helps!
setTimeout(function () {
var myImg = document.querySelector("#background");
var realWidth = myImg.naturalWidth;
var realHeight = myImg.naturalHeight;
$("canvas").attr("width", realWidth);
$("canvas").attr("height", realHeight);
var source = document.getElementById('background').src;
var canvas = new fabric.Canvas('canvas');
canvas.width = realWidth;
canvas.height = realHeight;
var ctx = canvas.getContext('2d');
document.getElementById('file').addEventListener("change", function (e) {
var file = e.target.files[0];
var reader = new FileReader();
reader.onload = function (f) {
var data = f.target.result;
fabric.Image.fromURL(data, function (img) {
var oImg = img.set({
left: 320
, top: 180
, angle: 00
, width: 200
, height: 200
});
canvas.add(oImg).renderAll();
var a = canvas.setActiveObject(oImg);
var dataURL = canvas.toDataURL({
format: 'png'
, quality: 0.8
});
});
};
reader.readAsDataURL(file);
});
canvas.setOverlayImage(source, canvas.renderAll.bind(canvas), {
backgroundImageOpacity: 0.5
, backgroundImageStretch: false
});
canvas.on('mouse:over', function (e) {
canvas.item(0).hasBorders = true;
canvas.item(0).hasControls = true;
canvas.setActiveObject(canvas.item(0));
});
canvas.on('mouse:out', function (e) {
canvas.item(0).hasBorders = false;
canvas.item(0).hasControls = false;
canvas.setActiveObject(canvas.item(0));
});
canvas.renderAll();
}, 2000);
$("#save").click(function () {
function blobCallback(iconName) {
return function (b) {
var a = document.getElementById('download');
a.download = iconName + ".jpg";
a.href = window.URL.createObjectURL(b);
}
}
canvas.toBlob(blobCallback('wallpaper'), 'image/vnd.microsoft.jpg', '-moz-parse-options:format=bmp;bpp=32');
});
.hide {
display: none;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cricmovie.com/bb-asserts/js/fabric.min.js"></script>
<body>
<div class="container"> <img src="http://cricmovie.com/bb-asserts/images/person.png" id="background" class="hide">
<input type="file" id="file">
<br />
<canvas id="canvas" class="img-responsive"></canvas>
</div>
<div class="container"> <a class="btn btn-primary" id="save">Save</a> <a class="btn btn-primary" id="download">Download</a> </div>
</body>
I am using fabric js to build a facemask application when i have two images
1) Image without face which is applied to canvas using setOverlayImage method
2) Only head where the user will upload and adjust accordingly.
I have almost done with functionality but I want to show fabric handlers above the first image where now they are hiding behind first image.
Reference Image : Click here for reference Image
Please find the Run Code Snippet
I think all you need to do is specify controlsAboveOverlay when you get the fabric instance.
var canvas = new fabric.Canvas('canvas', {
controlsAboveOverlay : true
});
Say I want to tailor my application to throttle throughput when running on battery power, but go full bore when it's plugged to a wall socket.
Is there an event to plug into to detect when these things happen like when internet connection is detected?
Apparently there's this trigger you can plug in to. It only fires off when the device is plugged in.
IE and WebView http://ie.microsoft.com/testdrive/HTML5/PowerMeter/Default.html can poll the cpu power states
eg: http://apps.microsoft.com/windows/app/plugged-in/2b91b1e1-9e30-4a96-bc95-b196e46bef9d
In c#/xaml try:
XAML
<WebView x:Name="BatteryCheck_WV" Source="ms-appx-web:///Assets/JSBatteryCheck.html" Height="50" Width="50" Visibility="Collapsed" />
c#
var PeriodicTimer = ThreadPoolTimer.CreatePeriodicTimer(async (timer) =>
{
await Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Low,
async () =>
{
if (Window.Current.Visible) BatteryStatus.IsOn= Convert.ToBoolean(await BatteryCheck_WV.InvokeScriptAsync("IsPluggedIn", null));
});
}, new TimeSpan(0, 0, 0, 1, 0));
html/js
<!DOCTYPE html>
<html>
<head>
<title>JSBatteryCheck</title>
<script type="text/javascript">
var batterytimeOut;
var timeOutGo = true;
var lastDisplayUpdateTime = new Date();
var MilliSeconds = 1000;
var displayUpdateInterval = 200;
var values = [];
var maxValues = displayUpdateInterval;
var PluggedIn = true;
var currentTicksPerMilliSecond = 0;
function GetTicksPerSecond() {
if ((new Date() - lastDisplayUpdateTime) >= displayUpdateInterval) {
lastDisplayUpdateTime = new Date;
currentTicksPerMilliSecond = Avg();
values = [];
if (!isNaN(currentTicksPerMilliSecond)) {
PluggedIn = (currentTicksPerMilliSecond > 9) ? false : true;
}
}
else Tick();
if (timeOutGo) batterytimeOut = setTimeout(function () { GetTicksPerSecond() }, 1);
}
function StartTimer() {
timeOutGo = true;
GetTicksPerSecond();
return "";
}
function Tick() {
if (values.length > maxValues) values.shift();
else values.push(new Date());
}
function Avg() {
if (values.length > 1) {
var earliest = values[0];
var latest = values[values.length - 1];
var elapsed = latest - earliest;
var elapsedSeconds = elapsed / MilliSeconds;
var avg = MilliSeconds / ((values.length - 1) / elapsedSeconds);
return parseInt(avg);
}
else return NaN;
}
function StopTimeOut() {
clearTimeout(batterytimeOut);
batterytimeOut = null;
timeOutGo = false;
}
function IsPluggedIn() {
return String(PluggedIn);
}
</script>
</head>
<body onload="GetTicksPerSecond()">
<div id="PowerStatus"></div>
<button onclick="StopTimeOut()">Stop timeout</button>
</body>
</html>
For background tasks SystemTriggerType.BackgroundWorkCostChange event is best but needs lock screen access