Build cross platform mobile apps with JavaScript and the Web
@@ -88,7 +88,7 @@ export class LandingPage {
Web Native
- Build apps with standardized web technologies that will work for decades, and
+ Build apps with standardized web technologies that will work for decades, and
easily reach users on the app stores and the mobile web.
@@ -96,7 +96,7 @@ export class LandingPage {
Extensible
- Easily add custom native functionality with a simple Plugin API, or
+ Easily add custom native functionality with a simple Plugin API, or
use existing Cordova plugins with our compatibility layer.
diff --git a/site/src/components/shader-player/shader-player.scss b/site/src/components/shader-player/shader-player.scss
new file mode 100644
index 0000000000..19f61aad46
--- /dev/null
+++ b/site/src/components/shader-player/shader-player.scss
@@ -0,0 +1,7 @@
+shader-player {
+ display: block;
+ canvas {
+ width: 100%;
+ height: 100%;
+ }
+}
diff --git a/site/src/components/shader-player/shader-player.tsx b/site/src/components/shader-player/shader-player.tsx
new file mode 100644
index 0000000000..830617d488
--- /dev/null
+++ b/site/src/components/shader-player/shader-player.tsx
@@ -0,0 +1,171 @@
+import { Component, Prop, Element, State, PropDidChange } from '@stencil/core';
+
+const DEFAULT_VERT = `attribute vec2 a_position;
+void main() {gl_Position = vec4(a_position, 0, 1);}`;
+
+const DEFAULT_FRAG = `void main() {gl_FragColor = vec4(0, 0, 0, 1);}`;
+
+@Component({
+ tag: 'shader-player',
+ styleUrl: 'shader-player.scss'
+})
+export class ShaderPlayer {
+
+ private glPosBuffer: WebGLBuffer;
+ private glProgram: WebGLProgram;
+ private gl: WebGLRenderingContext;
+ private canvas: HTMLCanvasElement;
+
+ @Element() el: HTMLElement;
+
+ @State() enabled = true;
+ @Prop() ready = true;
+
+ @Prop({ context: 'isServer' }) private isServer: boolean;
+
+
+ @Prop() vert: string = DEFAULT_VERT;
+ @Prop() retina = false;
+
+ @Prop() frag: string = DEFAULT_FRAG;
+ @Prop() uniforms: any = {};
+
+ @PropDidChange('vert')
+ @PropDidChange('frag')
+ shaderChanged() {
+ this.compileShader();
+ this.resolveUniforms();
+ this.renderGL();
+ }
+
+ @PropDidChange('uniforms')
+ uniformsChanged() {
+ this.resolveUniforms();
+ this.renderGL();
+ }
+
+ componentDidLoad() {
+ if(this.isServer) {
+ return;
+ }
+ this.canvas = this.el.querySelector('canvas');
+ this.resize();
+ const gl = this.gl = this.canvas.getContext('webgl');
+ if (!gl) {
+ console.warn('webgl is not available');
+ this.canvas = null;
+ this.enabled = false;
+ return;
+ }
+ this.initGL();
+ this.compileShader();
+ this.resolveUniforms();
+ this.renderGL();
+ }
+
+ private resize() {
+ const canvas = this.canvas;
+ if (!canvas) {
+ return;
+ }
+ const f = (this.retina) ? window.devicePixelRatio : 1;
+
+ // Lookup the size the browser is displaying the canvas.
+ const displayWidth = canvas.clientWidth * f;
+ const displayHeight = canvas.clientHeight * f;
+
+ // Check if the canvas is not the same size.
+ if (canvas.width !== displayWidth || canvas.height !== displayHeight) {
+
+ // Make the canvas the same size
+ canvas.width = displayWidth;
+ canvas.height = displayHeight;
+ if(this.gl) {
+ this.gl.viewport(0, 0, this.gl.drawingBufferWidth, this.gl.drawingBufferHeight);
+ }
+ }
+ }
+
+ private resolveUniforms() {
+ const gl = this.gl;
+ if (!gl) {
+ return;
+ }
+ const uniforms = this.uniforms;
+ const keys = Object.keys(uniforms);
+ gl.useProgram(this.glProgram);
+ for (let key of keys) {
+ const [prefix, uniform] = key.split(':', 2);
+ const loc = gl.getUniformLocation(this.glProgram, uniform);
+ const value = uniforms[key];
+ gl['uniform'+prefix](loc, value);
+ }
+ }
+
+ private initGL() {
+ const gl = this.gl;
+
+ gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+
+ const positionBuffer = this.glPosBuffer = gl.createBuffer();
+ gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
+ const positions = new Float32Array([
+ 1.0, 1.0,
+ -1.0, 1.0,
+ 1.0, -1.0,
+ -1.0, -1.0,
+ ]);
+ gl.bufferData(gl.ARRAY_BUFFER, positions, gl.STATIC_DRAW);
+ }
+
+ private compileShader() {
+ const gl = this.gl;
+ if (!gl) {
+ return;
+ }
+
+ const vertexShader = gl.createShader(gl.VERTEX_SHADER);
+ gl.shaderSource(vertexShader, this.vert);
+ gl.compileShader(vertexShader);
+
+ const fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
+ gl.shaderSource(fragmentShader, this.frag);
+ gl.compileShader(fragmentShader);
+
+ const program = this.glProgram = gl.createProgram();
+ gl.attachShader(program, vertexShader);
+ gl.attachShader(program, fragmentShader);
+ gl.linkProgram(program);
+ }
+
+ private renderGL() {
+ const gl = this.gl;
+ if (!gl) {
+ return;
+ }
+ if (!this.ready) {
+ gl.clearColor(0.03, 0.05, 0.07, 1.0);
+ gl.clear(gl.COLOR_BUFFER_BIT);
+ gl.flush();
+ return;
+ }
+
+ gl.bindBuffer(gl.ARRAY_BUFFER, this.glPosBuffer);
+
+ const positionLocation = gl.getAttribLocation(this.glProgram, "a_position");
+ gl.enableVertexAttribArray(positionLocation);
+ gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0);
+
+ gl.useProgram(this.glProgram);
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
+ }
+
+ render() {
+ if(this.enabled) {
+ this.resize();
+ return ;
+ } else {
+ return null;
+ }
+ }
+}
diff --git a/site/stencil.config.js b/site/stencil.config.js
index 9bfc1e610e..6edd99a2e3 100644
--- a/site/stencil.config.js
+++ b/site/stencil.config.js
@@ -1,7 +1,7 @@
exports.config = {
publicPath: 'build',
bundles: [
- { components: ['avocado-site', 'site-header', 'landing-page', 'lazy-iframe', 'site-menu'] },
+ { components: ['avocado-site', 'site-header', 'landing-page', 'landing-gl', 'shader-player', 'lazy-iframe', 'site-menu'] },
{ components: ['app-marked', 'document-component', 'doc-snippet', 'plugin-api', 'avc-code-type', 'anchor-link'] },
{ components: ['demos-page'] },
{ components: ['resources-page'] },
diff --git a/site/www/build/app.js b/site/www/build/app.js
index b588d16b9f..0b1b8cb4a9 100644
--- a/site/www/build/app.js
+++ b/site/www/build/app.js
@@ -1,2 +1,2 @@
/*! Built with http://stenciljs.com */
-!function(t,e,s,o,i,n,a,r){function c(t){return"noModule"in t}function p(t){return t.customElements}function u(t){return t.fetch}function l(t){return t.CSS&&t.CSS.supports&&t.CSS.supports("color","var(--c)")}function d(t){return t.documentElement.hasAttribute("data-ssr")}!function(t,e,s,o,i,n,a,r,h,m){(t[s]=t[s]||{}).components=r,(m=r.filter(function(t){return t[2]}).map(function(t){return t[0]})).length&&((h=e.createElement("style")).innerHTML=m.join()+"{visibility:hidden}",h.setAttribute("data-visibility",""),e.head.insertBefore(h,e.head.firstChild)),s=s.toLowerCase(),(h=e.scripts[e.scripts.length-1])&&h.src&&(o=(m=h.src.split("/").slice(0,-1)).join("/")+(m.length?"/":"")+s+"/"),(h=e.createElement("script")).src=o+(c(h)&&p(t)&&u(t)&&l(t)?d(e)?n:i:a),h.setAttribute("data-path",o),h.setAttribute("data-namespace",s),e.head.appendChild(h)}(window,document,"App","build/app/","app.qnefnhxv.js","app.gzgsz0co.js","app.m3eyznes.js",[["anchor-link",["sw8p3ksn","a67u4vho"],0,[["to",1,1,2]],0,1],["app-marked",["sw8p3ksn","a67u4vho"],1,[["content",5],["doc",1,1,2],["isServer",3,0,0,"isServer"]]],["avc-code-type",["sw8p3ksn","a67u4vho"],0,[["typeId",1,1,2]],0,1],["avocado-site",["6bo0uds8","px2eltlm"],1,[["isLandingPage",1,1,3]]],["blog-page",["lppew0yu","a9pov8p9"],1],["demos-page",["nvgxmkhh","rhlmfaus"],1],["doc-snippet",["sw8p3ksn","a67u4vho"]],["document-component",["sw8p3ksn","a67u4vho"],1,[["pages",1,1,1]]],["landing-page",["6bo0uds8","px2eltlm"],1,[["el",7]]],["lazy-iframe",["6bo0uds8","px2eltlm"],1,[["el",7],["realSrc",5],["src",1,1,2],["title",1,1,2]]],["plugin-api",["sw8p3ksn","a67u4vho"],1,[["content",5],["index",1,1,3],["name",1,1,2]]],["pwas-page",["krirex7d","9vp1kpca"],1],["resources-page",["n56a2jzp","lljbbqab"],1],["site-bar",["pxqetkvb","rjkvhcbv"],1],["site-header",["6bo0uds8","px2eltlm"],1],["site-menu",["6bo0uds8","px2eltlm"],1],["stencil-async-content",["xyfissap","pbssls7g"],0,[["content",5],["documentLocation",1,1,2]]],["stencil-route",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["component",1,1,2],["componentProps",1,1,1],["exact",1,1,3],["group",1,1,2],["location",3,0,0,"location"],["match",5],["routeRender",1,1,1],["url",1,1,1]]],["stencil-route-link",["xyfissap","pbssls7g"],0,[["activeClass",1,1,2],["activeRouter",3,0,0,"activeRouter"],["custom",1,1,3],["exact",1,1,3],["location",3,0,0,"location"],["match",5],["url",1,1,2],["urlMatch",1,1,1]],0,1],["stencil-route-title",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["title",1,1,2]]],["stencil-router",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["match",5],["root",1,1,2],["titleSuffix",1,1,2]],0,1],["stencil-router-redirect",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["url",1,1,2]]],["test-app",["cv7cbtbi","orsdhirh"]],["test-demo-four",["cv7cbtbi","orsdhirh"],0,[["history",1,1,1],["match",1,1,1],["pages",1,1,1]]],["test-demo-six",["cv7cbtbi","orsdhirh"],0,[["history",1,1,1],["match",1,1,1],["pages",1,1,1]]],["test-demo-three",["cv7cbtbi","orsdhirh"],0,[["history",1,1,1],["match",1,1,1],["pages",1,1,1]]]])}();
\ No newline at end of file
+!function(e,t,s,n,i,r,a,o){function c(e){return"noModule"in e}function p(e){return e.customElements}function u(e){return e.fetch}function l(e){return e.CSS&&e.CSS.supports&&e.CSS.supports("color","var(--c)")}function d(e){return e.documentElement.hasAttribute("data-ssr")}!function(e,t,s,n,i,r,a,o,h,v){(e[s]=e[s]||{}).components=o,(v=o.filter(function(e){return e[2]}).map(function(e){return e[0]})).length&&((h=t.createElement("style")).innerHTML=v.join()+"{visibility:hidden}",h.setAttribute("data-visibility",""),t.head.insertBefore(h,t.head.firstChild)),s=s.toLowerCase(),(h=t.scripts[t.scripts.length-1])&&h.src&&(n=(v=h.src.split("/").slice(0,-1)).join("/")+(v.length?"/":"")+s+"/"),(h=t.createElement("script")).src=n+(c(h)&&p(e)&&u(e)&&l(e)?d(t)?r:i:a),h.setAttribute("data-path",n),h.setAttribute("data-namespace",s),t.head.appendChild(h)}(window,document,"App","build/app/","app.qnefnhxv.js","app.gzgsz0co.js","app.m3eyznes.js",[["anchor-link",["sw8p3ksn","a67u4vho"],0,[["to",1,1,2]],0,1],["app-marked",["sw8p3ksn","a67u4vho"],1,[["content",5],["doc",1,1,2],["isServer",3,0,0,"isServer"]]],["avc-code-type",["sw8p3ksn","a67u4vho"],0,[["typeId",1,1,2]],0,1],["avocado-site",["5e0knrv8","hdynuipf"],1,[["isLandingPage",1,1,3]]],["blog-page",["lppew0yu","a9pov8p9"],1],["demos-page",["nvgxmkhh","rhlmfaus"],1],["doc-snippet",["sw8p3ksn","a67u4vho"]],["document-component",["sw8p3ksn","a67u4vho"],1,[["pages",1,1,1]]],["landing-gl",["5e0knrv8","hdynuipf"],0,[["data",5],["el",7],["isReady",5],["state",5]]],["landing-page",["5e0knrv8","hdynuipf"],1,[["el",7]]],["lazy-iframe",["5e0knrv8","hdynuipf"],1,[["el",7],["realSrc",5],["src",1,1,2],["title",1,1,2]]],["plugin-api",["sw8p3ksn","a67u4vho"],1,[["content",5],["index",1,1,3],["name",1,1,2]]],["pwas-page",["krirex7d","9vp1kpca"],1],["resources-page",["n56a2jzp","lljbbqab"],1],["shader-player",["5e0knrv8","hdynuipf"],1,[["el",7],["enabled",5],["frag",1,1,2],["isServer",3,0,0,"isServer"],["ready",1,1,3],["retina",1,1,3],["uniforms",1,1,1],["vert",1,1,2]]],["site-bar",["pxqetkvb","rjkvhcbv"],1],["site-header",["5e0knrv8","hdynuipf"],1],["site-menu",["5e0knrv8","hdynuipf"],1],["stencil-async-content",["xyfissap","pbssls7g"],0,[["content",5],["documentLocation",1,1,2]]],["stencil-route",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["component",1,1,2],["componentProps",1,1,1],["exact",1,1,3],["group",1,1,2],["location",3,0,0,"location"],["match",5],["routeRender",1,1,1],["url",1,1,1]]],["stencil-route-link",["xyfissap","pbssls7g"],0,[["activeClass",1,1,2],["activeRouter",3,0,0,"activeRouter"],["custom",1,1,3],["exact",1,1,3],["location",3,0,0,"location"],["match",5],["url",1,1,2],["urlMatch",1,1,1]],0,1],["stencil-route-title",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["title",1,1,2]]],["stencil-router",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["match",5],["root",1,1,2],["titleSuffix",1,1,2]],0,1],["stencil-router-redirect",["xyfissap","pbssls7g"],0,[["activeRouter",3,0,0,"activeRouter"],["url",1,1,2]]],["test-app",["cv7cbtbi","orsdhirh"]],["test-demo-four",["cv7cbtbi","orsdhirh"],0,[["history",1,1,1],["match",1,1,1],["pages",1,1,1]]],["test-demo-six",["cv7cbtbi","orsdhirh"],0,[["history",1,1,1],["match",1,1,1],["pages",1,1,1]]],["test-demo-three",["cv7cbtbi","orsdhirh"],0,[["history",1,1,1],["match",1,1,1],["pages",1,1,1]]]])}();
\ No newline at end of file
diff --git a/site/www/build/app/app.global.js b/site/www/build/app/app.global.js
index b33405723f..95ea2a52c4 100644
--- a/site/www/build/app/app.global.js
+++ b/site/www/build/app/app.global.js
@@ -1,114 +1,5 @@
/*! Built with http://stenciljs.com */
(function(appNamespace,publicPath){"use strict";
-(function(publicPath){
- /** @stencil/router global **/
-
- var __assign = (undefined && undefined.__assign) || Object.assign || function(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
- t[p] = s[p];
- }
- return t;
- };
- Context.activeRouter = (function () {
- var state = {};
- var groups = {};
- var matchedGroups = {};
- var nextListeners = [];
- function getDefaultState() {
- return {
- location: {
- pathname: Context.window.location.pathname,
- search: Context.window.location.search
- }
- };
- }
- function set(value) {
- state = __assign({}, state, value);
- clearGroups();
- dispatch();
- }
- function get(attrName) {
- if (Object.keys(state).length === 0) {
- return getDefaultState();
- }
- if (!attrName) {
- return state;
- }
- return state[attrName];
- }
- /**
- * When we get a new location, clear matching groups
- * so we give them a chance to re-match and re-render.
- */
- function clearGroups() {
- matchedGroups = {};
- }
- function dispatch() {
- var listeners = nextListeners;
- for (var i = 0; i < listeners.length; i++) {
- var listener = listeners[i];
- listener();
- }
- }
- function subscribe(listener) {
- if (typeof listener !== 'function') {
- throw new Error('Expected listener to be a function.');
- }
- var isSubscribed = true;
- nextListeners.push(listener);
- return function unsubscribe() {
- if (!isSubscribed) {
- return;
- }
- isSubscribed = false;
- var index = nextListeners.indexOf(listener);
- nextListeners.splice(index, 1);
- };
- }
- /**
- * Remove a Route from all groups
- */
- function removeFromGroups(route) {
- for (var groupName in groups) {
- var group = groups[groupName];
- groups[groupName] = group.filter(function (r) { return r !== route; });
- }
- }
- /**
- * Add a Route to the given group
- */
- function addToGroup(route, groupName) {
- if (!(groupName in groups)) {
- groups[groupName] = [];
- }
- groups[groupName].push(route);
- }
- /**
- * Check if a group already matched once
- */
- function didGroupAlreadyMatch(groupName) {
- if (!groupName) {
- return false;
- }
- return matchedGroups[groupName] === true;
- }
- /**
- * Set that a group has matched
- */
- function setGroupMatched(groupName) {
- matchedGroups[groupName] = true;
- }
- return {
- set: set,
- get: get,
- subscribe: subscribe,
- addToGroup: addToGroup,
- removeFromGroups: removeFromGroups,
- didGroupAlreadyMatch: didGroupAlreadyMatch,
- setGroupMatched: setGroupMatched
- };
- })();
+(function(publicPath){var __assign=Object.assign||function(n){for(var t,r=1,o=arguments.length;r;rel=preload;as=script"
+ "value": ";rel=preload;as=script"
},
{
"name": "Link",
diff --git a/site/www/index.html b/site/www/index.html
index 48b6c7d86a..4be538ce05 100644
--- a/site/www/index.html
+++ b/site/www/index.html
@@ -1,6 +1,40 @@
- Capacitor: Universal Web Applications
+ Capacitor: Universal Web Applications
-
Build cross platform mobile apps with JavaScript and the Web
Native Progressive Web Apps with HTML, CSS, and JavaScript
Coming early 2018. Sign up below for updates
Cross Platform
Build web apps that run equally well on iOS, Android, Electron, and as Progressive Web Apps
Native Access
Access the full Native SDK on each platform, and easily deploy to App Stores (and the web!)
Open Source
Capacitor is completely open source (MIT) and maintained by Ionic and its community.
Web Native
Build apps with standardized web technologies that will work for decades, and easily reach users on the app stores and the mobile web.
Extensible
Easily build custom native plugins and functionality with a simple Plugin API, or use existing Cordova plugins with our compatibility layer.
Simple
Focus on what you want to do, not how. Capacitor turns complex, proprietary Native APIs into simple JS calls.