初始化

This commit is contained in:
yziiy
2025-08-11 11:06:07 +08:00
parent 083bc37c00
commit 5607d11395
19772 changed files with 3108723 additions and 18 deletions

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="ES6" />
</component>
</project>

View File

@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/safeAreaInsets.iml" filepath="$PROJECT_DIR$/.idea/safeAreaInsets.iml" />
</modules>
</component>
</project>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@@ -0,0 +1,57 @@
# safeAreaInsets
使用javascript获取安全区信息.
## 先决条件
* WKWebview
* viewport-fit=cover
## 安装
### NPM
```shell
npm install safe-area-insets --save
```
### UMD
```http
https://unpkg.com/safe-area-insets/out/umd/index.min.js
```
## 使用
### 引用
```js
var safeAreaInsets = require('safe-area-insets')
```
### 安全区信息
```js
console.log('safeAreaInsets.support', safeAreaInsets.support)
console.log('safe-area-inset-top', safeAreaInsets.top)
console.log('safe-area-inset-left', safeAreaInsets.left)
console.log('safe-area-inset-right', safeAreaInsets.right)
console.log('safe-area-inset-bottom', safeAreaInsets.bottom)
```
### 监听安全区信息变化事件
```js
function callback(style){
console.log(style)
}
// add
safeAreaInsets.onChange(callback)
// remove
safeAreaInsets.offChange(callback)
```
## 相关阅读
>[为iPhoneX设计网站](https://webkit.org/blog/7929/designing-websites-for-iphone-x/)

View File

@@ -0,0 +1,58 @@
# safeAreaInsets
Use javascript to get the safe area insets.
Chinese documentation : [中文文档](https://github.com/zhetengbiji/safeAreaInsets/blob/master/README-CH.md)
## Precondition
* WKWebview
* viewport-fit=cover
## Install
### NPM
```
npm install safe-area-insets --save
```
### UMD
```http
https://unpkg.com/safe-area-insets/out/umd/index.min.js
```
## Use
### Require
```js
const safeAreaInsets = require('safe-area-insets')
```
### Safe Area Info
```js
console.log('safeAreaInsets.support', safeAreaInsets.support)
console.log('safe-area-inset-top', safeAreaInsets.top)
console.log('safe-area-inset-left', safeAreaInsets.left)
console.log('safe-area-inset-right', safeAreaInsets.right)
console.log('safe-area-inset-bottom', safeAreaInsets.bottom)
```
### Listening Change Event
```js
function callback(style){
console.log(style)
}
// add
safeAreaInsets.onChange(callback)
// remove
safeAreaInsets.offChange(callback)
```
## Related Reading
>[Designing Websites for iPhone X](https://webkit.org/blog/7929/designing-websites-for-iphone-x/)

View File

@@ -0,0 +1,12 @@
declare function onChange(callback: Function): void;
declare function offChange(callback: Function): void;
declare var safeAreaInsets: {
readonly support: boolean;
readonly top: number;
readonly left: number;
readonly right: number;
readonly bottom: number;
onChange: typeof onChange;
offChange: typeof offChange;
};
export = safeAreaInsets;

View File

@@ -0,0 +1,193 @@
'use strict';
var attrs = ['top', 'left', 'right', 'bottom'];
var inited;
var elementComputedStyle = {};
var support;
function getSupport() {
if (!('CSS' in window) || typeof CSS.supports != 'function') {
support = '';
}
else if (CSS.supports('top: env(safe-area-inset-top)')) {
support = 'env';
}
else if (CSS.supports('top: constant(safe-area-inset-top)')) {
support = 'constant';
}
else {
support = '';
}
return support;
}
function init() {
support = typeof support === 'string' ? support : getSupport();
if (!support) {
attrs.forEach(function (attr) {
elementComputedStyle[attr] = 0;
});
return;
}
function setStyle(el, style) {
var elStyle = el.style;
Object.keys(style).forEach(function (key) {
var val = style[key];
elStyle[key] = val;
});
}
var cbs = [];
function parentReady(callback) {
if (callback) {
cbs.push(callback);
}
else {
cbs.forEach(function (cb) {
cb();
});
}
}
var passiveEvents = false;
try {
var opts = Object.defineProperty({}, 'passive', {
get: function () {
passiveEvents = { passive: true };
}
});
window.addEventListener('test', null, opts);
}
catch (e) {
}
function addChild(parent, attr) {
var a1 = document.createElement('div');
var a2 = document.createElement('div');
var a1Children = document.createElement('div');
var a2Children = document.createElement('div');
var W = 100;
var MAX = 10000;
var aStyle = {
position: 'absolute',
width: W + 'px',
height: '200px',
boxSizing: 'border-box',
overflow: 'hidden',
paddingBottom: support + "(safe-area-inset-" + attr + ")"
};
setStyle(a1, aStyle);
setStyle(a2, aStyle);
setStyle(a1Children, {
transition: '0s',
animation: 'none',
width: '400px',
height: '400px'
});
setStyle(a2Children, {
transition: '0s',
animation: 'none',
width: '250%',
height: '250%'
});
a1.appendChild(a1Children);
a2.appendChild(a2Children);
parent.appendChild(a1);
parent.appendChild(a2);
parentReady(function () {
a1.scrollTop = a2.scrollTop = MAX;
var a1LastScrollTop = a1.scrollTop;
var a2LastScrollTop = a2.scrollTop;
function onScroll() {
if (this.scrollTop === (this === a1 ? a1LastScrollTop : a2LastScrollTop)) {
return;
}
a1.scrollTop = a2.scrollTop = MAX;
a1LastScrollTop = a1.scrollTop;
a2LastScrollTop = a2.scrollTop;
attrChange(attr);
}
a1.addEventListener('scroll', onScroll, passiveEvents);
a2.addEventListener('scroll', onScroll, passiveEvents);
});
var computedStyle = getComputedStyle(a1);
Object.defineProperty(elementComputedStyle, attr, {
configurable: true,
get: function () {
return parseFloat(computedStyle.paddingBottom);
}
});
}
var parentDiv = document.createElement('div');
setStyle(parentDiv, {
position: 'absolute',
left: '0',
top: '0',
width: '0',
height: '0',
zIndex: '-1',
overflow: 'hidden',
visibility: 'hidden',
});
attrs.forEach(function (key) {
addChild(parentDiv, key);
});
document.body.appendChild(parentDiv);
parentReady();
inited = true;
}
function getAttr(attr) {
if (!inited) {
init();
}
return elementComputedStyle[attr];
}
var changeAttrs = [];
function attrChange(attr) {
if (!changeAttrs.length) {
setTimeout(function () {
var style = {};
changeAttrs.forEach(function (attr) {
style[attr] = elementComputedStyle[attr];
});
changeAttrs.length = 0;
callbacks.forEach(function (callback) {
callback(style);
});
}, 0);
}
changeAttrs.push(attr);
}
var callbacks = [];
function onChange(callback) {
if (!getSupport()) {
return;
}
if (!inited) {
init();
}
if (typeof callback === 'function') {
callbacks.push(callback);
}
}
function offChange(callback) {
var index = callbacks.indexOf(callback);
if (index >= 0) {
callbacks.splice(index, 1);
}
}
var safeAreaInsets = {
get support() {
return (typeof support === 'string' ? support : getSupport()).length != 0;
},
get top() {
return getAttr('top');
},
get left() {
return getAttr('left');
},
get right() {
return getAttr('right');
},
get bottom() {
return getAttr('bottom');
},
onChange: onChange,
offChange: offChange
};
module.exports = safeAreaInsets;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define("safeAreaInsets",[],e):"object"==typeof exports?exports.safeAreaInsets=e():t.safeAreaInsets=e()}("undefined"!=typeof self?self:this,function(){return function(t){function e(o){if(n[o])return n[o].exports;var r=n[o]={i:o,l:!1,exports:{}};return t[o].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};return e.m=t,e.c=n,e.d=function(t,n,o){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:o})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=0)}([function(t,e,n){"use strict";function o(){return a="CSS"in window&&"function"==typeof CSS.supports?CSS.supports("top: env(safe-area-inset-top)")?"env":CSS.supports("top: constant(safe-area-inset-top)")?"constant":"":""}function r(){function t(t,e){var n=t.style;Object.keys(e).forEach(function(t){var o=e[t];n[t]=o})}function e(t){t?r.push(t):r.forEach(function(t){t()})}function n(n,o){var r=document.createElement("div"),f=document.createElement("div"),s=document.createElement("div"),u=document.createElement("div"),p=1e4,l={position:"absolute",width:"100px",height:"200px",boxSizing:"border-box",overflow:"hidden",paddingBottom:a+"(safe-area-inset-"+o+")"};t(r,l),t(f,l),t(s,{transition:"0s",animation:"none",width:"400px",height:"400px"}),t(u,{transition:"0s",animation:"none",width:"250%",height:"250%"}),r.appendChild(s),f.appendChild(u),n.appendChild(r),n.appendChild(f),e(function(){function t(){this.scrollTop!==(this===r?e:n)&&(r.scrollTop=f.scrollTop=p,e=r.scrollTop,n=f.scrollTop,c(o))}r.scrollTop=f.scrollTop=p;var e=r.scrollTop,n=f.scrollTop;r.addEventListener("scroll",t,i),f.addEventListener("scroll",t,i)});var h=getComputedStyle(r);Object.defineProperty(d,o,{configurable:!0,get:function(){return parseFloat(h.paddingBottom)}})}if(!(a="string"==typeof a?a:o()))return void p.forEach(function(t){d[t]=0});var r=[],i=!1;try{var f=Object.defineProperty({},"passive",{get:function(){i={passive:!0}}});window.addEventListener("test",null,f)}catch(t){}var s=document.createElement("div");t(s,{position:"absolute",left:"0",top:"0",width:"0",height:"0",zIndex:"-1",overflow:"hidden",visibility:"hidden"}),p.forEach(function(t){n(s,t)}),document.body.appendChild(s),e(),u=!0}function i(t){return u||r(),d[t]}function c(t){l.length||setTimeout(function(){var t={};l.forEach(function(e){t[e]=d[e]}),l.length=0,h.forEach(function(e){e(t)})},0),l.push(t)}function f(t){o()&&(u||r(),"function"==typeof t&&h.push(t))}function s(t){var e=h.indexOf(t);e>=0&&h.splice(e,1)}var u,a,p=["top","left","right","bottom"],d={},l=[],h=[],b={get support(){return 0!=("string"==typeof a?a:o()).length},get top(){return i("top")},get left(){return i("left")},get right(){return i("right")},get bottom(){return i("bottom")},onChange:f,offChange:s};t.exports=b}])});

View File

@@ -0,0 +1,31 @@
{
"name": "safe-area-insets",
"version": "1.4.1",
"description": "Use javascript to get the safe area insets.",
"main": "out/index.js",
"types": "out/index.d.ts",
"scripts": {
"prepublish": "npm run build",
"build": "tsc -p . && node build"
},
"repository": {
"type": "git",
"url": "git+https://github.com/zhetengbiji/safeAreaInsets.git"
},
"keywords": [
"safari",
"iphonex",
"safeAreaInsets"
],
"author": "Shengqiang Guo",
"license": "ISC",
"bugs": {
"url": "https://github.com/zhetengbiji/safeAreaInsets/issues"
},
"homepage": "https://github.com/zhetengbiji/safeAreaInsets#readme",
"devDependencies": {
"ts-loader": "^3.3.1",
"typescript": "^2.9.1",
"webpack": "^3.12.0"
}
}

View File

@@ -0,0 +1,203 @@
'use strict'
var attrs: string[] = ['top', 'left', 'right', 'bottom']
var inited: boolean
var elementComputedStyle = {}
var support: string
function getSupport() {
if(!('CSS' in window) || typeof CSS.supports != 'function') {
support = ''
} else if(CSS.supports('top: env(safe-area-inset-top)')) {
support = 'env'
} else if(CSS.supports('top: constant(safe-area-inset-top)')) {
support = 'constant'
} else {
support = ''
}
return support
}
function init() {
support = typeof support === 'string' ? support : getSupport()
if(!support) {
attrs.forEach((attr: string) => {
elementComputedStyle[attr] = 0
})
return
}
function setStyle(el: HTMLElement, style) {
var elStyle: CSSStyleDeclaration = el.style
Object.keys(style).forEach(key => {
var val: string = style[key]
elStyle[key] = val
})
}
var cbs: Function[] = []
function parentReady(callback?: Function) {
if(callback) {
cbs.push(callback)
} else {
cbs.forEach(cb => {
cb()
})
}
}
var passiveEvents: any = false
try {
var opts = Object.defineProperty({}, 'passive', {
get: function() {
passiveEvents = { passive: true }
}
})
window.addEventListener('test', null, opts)
} catch(e) {
}
function addChild(parent: HTMLElement, attr: string) {
var a1: HTMLElement = document.createElement('div')
var a2: HTMLElement = document.createElement('div')
var a1Children: HTMLElement = document.createElement('div')
var a2Children: HTMLElement = document.createElement('div')
var W: number = 100
var MAX: number = 10000
var aStyle = {
position: 'absolute',
width: W + 'px',
height: '200px',
boxSizing: 'border-box',
overflow: 'hidden',
paddingBottom: `${support}(safe-area-inset-${attr})`
}
setStyle(a1, aStyle)
setStyle(a2, aStyle)
setStyle(a1Children, {
transition: '0s',
animation: 'none',
width: '400px',
height: '400px'
})
setStyle(a2Children, {
transition: '0s',
animation: 'none',
width: '250%',
height: '250%'
})
a1.appendChild(a1Children)
a2.appendChild(a2Children)
parent.appendChild(a1)
parent.appendChild(a2)
parentReady(() => {
a1.scrollTop = a2.scrollTop = MAX
var a1LastScrollTop: number = a1.scrollTop
var a2LastScrollTop: number = a2.scrollTop
function onScroll() {
if(this.scrollTop === (this === a1 ? a1LastScrollTop : a2LastScrollTop)) {
return
}
a1.scrollTop = a2.scrollTop = MAX
a1LastScrollTop = a1.scrollTop
a2LastScrollTop = a2.scrollTop
attrChange(attr)
}
a1.addEventListener('scroll', onScroll, passiveEvents)
a2.addEventListener('scroll', onScroll, passiveEvents)
})
var computedStyle: CSSStyleDeclaration = getComputedStyle(a1)
Object.defineProperty(elementComputedStyle, attr, {
configurable: true,
get() {
return parseFloat(computedStyle.paddingBottom)
}
})
}
var parentDiv: HTMLElement = document.createElement('div')
setStyle(parentDiv, {
position: 'absolute',
left: '0',
top: '0',
width: '0',
height: '0',
zIndex: '-1',
overflow: 'hidden',
visibility: 'hidden',
})
attrs.forEach(key => {
addChild(parentDiv, key)
})
document.body.appendChild(parentDiv)
parentReady()
inited = true
}
function getAttr(attr: string): number {
if(!inited) {
init()
}
return elementComputedStyle[attr]
}
var changeAttrs: string[] = []
function attrChange(attr: string) {
if(!changeAttrs.length) {
setTimeout(() => {
var style = {}
changeAttrs.forEach(attr => {
style[attr] = elementComputedStyle[attr]
})
changeAttrs.length = 0
callbacks.forEach(callback => {
callback(style)
})
}, 0)
}
changeAttrs.push(attr)
}
var callbacks: Function[] = []
function onChange(callback: Function) {
if(!getSupport()) {
return
}
if(!inited) {
init()
}
if(typeof callback === 'function') {
callbacks.push(callback)
}
}
function offChange(callback: Function) {
var index = callbacks.indexOf(callback)
if(index >= 0){
callbacks.splice(index, 1)
}
}
var safeAreaInsets = {
get support(): boolean {
return (typeof support === 'string' ? support : getSupport()).length != 0
},
get top(): number {
return getAttr('top')
},
get left(): number {
return getAttr('left')
},
get right(): number {
return getAttr('right')
},
get bottom(): number {
return getAttr('bottom')
},
onChange,
offChange
}
export = safeAreaInsets