0%

git pull是git fetch和git merge两个步骤的结合

vscode 的 sync 等于下面

1
2
git pull origin someBranch
git push origin someBranch

  • ~ 选择器的 相反的 “previous sibling” selector ?

几个思路:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* default link color is blue */
.parent a {
color: blue;
}

/* prev siblings should be red */
.parent:hover a {
color: red;
}
.parent a:hover,
.parent a:hover ~ a {
color: blue;
}
1
2
3
4
5
6
7
<div class="parent">
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
<a href="#">link</a>
</div>

flex order 或者 row-reverse 。 DOM 在后但显示“在前”。

1
ul li:nth-child(-n+2)

via https://stackoverflow.com/questions/1817792/is-there-a-previous-sibling-selector

via https://coolcssanimation.com/how-to-trigger-a-css-animation-on-scroll/


IntersectionObserver 是否可见

1
2
3
4
5
6
7
8
9
10
11
12
13
var io = new IntersectionObserver(callback, option);

// 开始观察
io.observe(document.getElementById('example'));

// 停止观察
io.unobserve(element);

// 关闭观察器
io.disconnect();

io.observe(elementA);
io.observe(elementB);

lazy load

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function query(selector) {
return Array.from(document.querySelectorAll(selector));
}

var observer = new IntersectionObserver(
function(changes) {
changes.forEach(function(change) {
var container = change.target;
var content = container.querySelector('template').content;
container.appendChild(content);
observer.unobserve(container);
});
}
);

query('.lazy-loaded').forEach(function (item) {
observer.observe(item);
});

无限滚动(infinite scroll)

1
2
3
4
5
6
7
8
9
10
11
12
var intersectionObserver = new IntersectionObserver(
function (entries) {
// 如果不可见,就返回
if (entries[0].intersectionRatio <= 0) return;
loadItems(10);
console.log('Loaded new items');
});

// 开始观察
intersectionObserver.observe(
document.querySelector('.scrollerFooter')
);

ResizeObserver

观测 resize

scrollIntoView 到中间

https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollIntoView

scrollIntoView()

默认是

scrollIntoView(true)

也就是

scrollIntoView({block: “start”, inline: “nearest”})

false 是

scrollIntoView({block: “end”, inline: “nearest”})

参数

behavior Optional

Defines the transition animation. One of auto or smooth. Defaults to auto.

block Optional

Defines vertical alignment. One of start, center, end, or nearest. Defaults to start.

inline Optional

Defines horizontal alignment. One of start, center, end, or nearest. Defaults to nearest.

tab 尽量靠中间

1
2
3
4
5
6
7
obj.scrollIntoView(
{
behavior: 'smooth',
block: 'nearest',
inline: 'center'
}
)

16:9 固定比例的 iframe

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.container {
position: relative;
overflow: hidden;
width: 100%;
padding-top: 56.25%; /* 16:9 Aspect Ratio (divide 9 by 16 = 0.5625) */
}

/* Then style the iframe to fit in the container div with full height and width */
.responsive-iframe {
position: absolute;
top: 0;
left: 0;
bottom: 0;
right: 0;
width: 100%;
height: 100%;
}

class add active

1
2
3
4
5
6
7
8
9
10
11
12
13
for (var i = 0; i < btns.length; i++) {
btns[i].addEventListener("click", function() {
var current = document.getElementsByClassName("active");

// If there's no active class
if (current.length > 0) {
current[0].className = current[0].className.replace(" active", "");
}

// Add the active class to the current/clicked button
this.className += " active";
});
}

Get Element in Iframe

1
2
3
var iframe = document.getElementById("myFrame");
var elmnt = iframe.contentWindow.document.getElementsByTagName("H1")[0];
elmnt.style.display = "none";

Media Queries with JavaScrip

1
2
3
4
5
6
7
8
9
10
11
function myFunction(x) {
if (x.matches) { // If media query matches
document.body.style.backgroundColor = "yellow";
} else {
document.body.style.backgroundColor = "pink";
}
}

var x = window.matchMedia("(max-width: 700px)")
myFunction(x) // Call listener function at run time
x.addListener(myFunction) // Attach listener function on state changes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<defs>
<linearGradient
id="grad1"
x1="0%"
y1="0%"
x2="100%"
y2="0%"
>
<stop
offset="0%"
style="stop-color:#8095F0;stop-opacity:1"
/>
<stop
offset="100%"
style="stop-color:#51FCB5;stop-opacity:1"
/>
</linearGradient>
</defs>

1
2
3
4
5
6
'fill-color': ['interpolate-hcl', ['linear'], ['feature-state', 'population'], 0, 'red', 1e6, 'blue']


for (const district of districts) {
map.setFeatureState({ source: 'mysource', sourceLayer: 'mysourcelayer', id: district.id }, { population: district.population});
}
1
2
3
4
5
6
'fill-color': ['match', ['get', 'id'],
1020, 'red',
1033, 'green',
1038, 'red',
1049, 'white',
// ...
1
2
3
4
5
6
7
8
"icon-image": [
"case",
["all", ["==", ["get", "matched"], "True"], ["!=", ["get", "vehicle"], ["get", "standstill_vehicle"]]],
"orangemarker",
["==", ["get", "matched"], "True"],
"greenmarker",
"redmarker",
]
1
2
3
4
5
this.map.setPaintProperty("somelayer", "fill-color",
["case",
["==", ["get", "some_prop"], someval], "#34c0dd",
"#499bbc"
]);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const layers = [{
id: 'countries',
type: 'fill',
source: 'countries',
paint: {
'fill-color': [
'match', ['get', 'filter_prop', ['global']],
'pop_est',
['step', ['get', 'pop_est'],
0, '#f8d5cc',
1000000, '#f4bfb6',
5000000, '#f1a8a5',
10000000, '#ee8f9a',
50000000, '#ec739b',
100000000, '#dd5ca8',
250000000, '#c44cc0',
500000000, '#9f43d7',
1000000000, '#6e40e6',
],
'gdp_md_est',
['step', ['get', 'gdp_md_est'],
0, '#f8d5cc',
1000, '#f4bfb6',
5000, '#f1a8a5',
10000, '#ee8f9a',
50000, '#ec739b',
100000, '#dd5ca8',
250000, '#c44cc0',
5000000, '#9f43d7',
10000000, '#6e40e6',
],
'#ffffff',
],
},
}];

以下这个未测试!

1
2
3
4
5
6
['step', ['zoom'],
['case', ['all', ['!', ['feature-state', 'hidden']], ['get', 'red'], 1, 0],
10,
['case', ['all', ['!', ['feature-state', 'hidden']], ['any', ['get', 'red'], ['get', 'green']], 1, 0],
15,
['case', [['!', ['feature-state', 'hidden']], 1, 0]],
1
2
3
4
5
6
7
8
9
10
11
12
13
14
map.addLayer({
id: "cluster-count",
type: "symbol",
source: "grundbuch",
filter: ["has", "point_count"],
layout: {
"text-field": "{point_count_abbreviated}",
"text-font": ["DIN Offc Pro Medium", "Arial Unicode MS Bold"],
"text-size": 12
},
paint: {
"text-color": "#ffffff"
}
});

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
"line-color": [
'case',
['boolean', ['feature-state', 'hover'], false],
'#c00',

[
'case',
['!=', ['get', 'color'], null],
['get', 'color'],
'#16e8e9'
]

],
````

###

test.map.showCollisionBoxes = true // 显示碰撞边界
test.map.showTileBoundaries = true // 显示tile边界
test.map.showOverdrawInspector = true

需要很习惯一段时间

### setFeatureState

if (quakeID) {
map.removeFeatureState({
source: “earthquakes”,
id: quakeID
});
}
map.setFeatureState({
source: ‘earthquakes’,
id: quakeID,
}, {
hover: true
});

1
2


map.addLayer({
‘id’: ‘earthquakes-viz’,
‘type’: ‘circle’,
‘source’: ‘earthquakes’,
‘paint’: {
// The feature-state dependent circle-radius expression will render
// the radius size according to its magnitude when
// a feature’s hover state is set to true
‘circle-radius’: [
‘case’,
[‘boolean’,
[‘feature-state’, ‘hover’],
false
],
[
‘interpolate’, [‘linear’],
[‘get’, ‘mag’],
1, 8,
1.5, 10,
2, 12,
2.5, 14,
3, 16,
3.5, 18,
4.5, 20,
6.5, 22,
8.5, 24,
10.5, 26
],
5
],
‘circle-stroke-color’: ‘#000’,
‘circle-stroke-width’: 1,
// The feature-state dependent circle-color expression will render
// the color according to its magnitude when
// a feature’s hover state is set to true
‘circle-color’: [
‘case’,
[‘boolean’,
[‘feature-state’, ‘hover’],
false
],
[
‘interpolate’, [‘linear’],
[‘get’, ‘mag’],
1, ‘#fff7ec’,
1.5, ‘#fee8c8’,
2, ‘#fdd49e’,
2.5, ‘#fdbb84’,
3, ‘#fc8d59’,
3.5, ‘#ef6548’,
4.5, ‘#d7301f’,
6.5, ‘#b30000’,
8.5, ‘#7f0000’,
10.5, ‘#000’
],
‘#000’
]
}
});

````

via https://docs.mapbox.com/help/tutorials/create-interactive-hover-effects-with-mapbox-gl-js/

examples

var aa = { “type”: “Polygon”,
“coordinates”: [
[
[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ]
]
}

var aa = { “type”: “Polygon”,
“coordinates”: [
[ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ],
[ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ]
]
}

test.map.getSource(‘temp_line’).setData(aa)

{
type:’FeatureCollection’,
features:[
{
“geometry”: {
“type”: “MultiPoint”,
“coordinates”: [
[
108.91373500227928,
34.241324229728534
],
]
},
“type”: “Feature”,

}
]
}

1
Array.prototype.push.apply(a, [1,2]))

a.push(1, 2, 3);

1
2
3
4
var arr = [1];
var newItems = [2, 3];
arr.push(...newItems);
console.log(arr);

思路如下(console中有三个数据)

  • 后台请求(adss类型的)物理光缆 wlgl
  • 获得(界面中)铁路数据 railway
  • 计算 railway 和 wlgl 交叉点
  • groupBy 业务光缆,items push 所有点。然后去重为 items2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}

async function demo() {
console.log('Taking a break...');
await sleep(2000);
console.log('Two seconds later, showing sleep in a loop...');

// Sleep in loop
for (let i = 0; i < 5; i++) {
if (i === 3)
await sleep(2000);
console.log(i);
}
}

demo();

via https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep

layer chnage source

其实是重建

1
2
3
4
5
6
7
8
9
10
11
12
function setLayerSource (layerId, source, sourceLayer) {
const oldLayers = map.getStyle().layers;
const layerIndex = oldLayers.findIndex(l => l.id === layerId);
const layerDef = oldLayers[layerIndex];
const before = oldLayers[layerIndex + 1] && oldLayers[layerIndex + 1].id;
layerDef.source = source;
if (sourceLayer) {
layerDef['source-layer'] = sourceLayer;
}
map.removeLayer(layerId);
map.addLayer(layerDef, before);
}

https://github.com/mapbox/mapbox-gl-js/issues/1722

  • 为对象添加属性
  • 为对象添加方法
  • 浅克隆
  • 合并多个对象
  • 属性指定默认值
1
2
3
4
5
6
7
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
let options = Object.assign({}, DEFAULTS, options);
}

Object.create()、new Object()和{}的区别

直接字面量创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var objA = {};
objA.name = 'a';
objA.sayName = function() {
console.log(`My name is ${this.name} !`);
}
// var objA = {
// name: 'a',
// sayName: function() {
// console.log(`My name is ${this.name} !`);
// }
// }
objA.sayName();
console.log(objA.__proto__ === Object.prototype); // true
console.log(objA instanceof Object); // true

new关键字创建

1
2
3
4
5
6
7
8
9
var objB = new Object();
// var objB = Object();
objB.name = 'b';
objB.sayName = function() {
console.log(`My name is ${this.name} !`);
}
objB.sayName();
console.log(objB.__proto__ === Object.prototype); // true
console.log(objB instanceof Object); // true

Object.create 创建

一个完整的版本

https://ouyangresume.github.io/2019/12/19/mapbox%E7%9A%84Popup%E4%B8%8EVue%E6%A1%86%E6%9E%B6%E8%9E%8D%E5%90%88%E4%BD%BF%E7%94%A8/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import StarRating from 'vue-star-rating'

// ...

var starRating = new Vue({
...StarRating,
parent: this,
propsData: { /* pass props here*/ }
}).$mount()

starRating.$on('someEvent', (value) => {
// listen to events emitted from the component
})
var popup = new mapboxgl.Popup()
.setDOMContent(startRating.$el)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import InfoWindowContent from '../InfoWindowContent.vue'

L.popup({maxWidth: 600,
className: 'leaflet-info-window'})
.setLatLng(latlng)
.setContent('<div id="info-window"></div>')
.openOn(this.map)
const InfoWindow = Vue.extend(InfoWindowContent)
const infoWindow = new InfoWindow({
propsData: {
windowData: this.infoWindowData,
windowType: this.infoWindowType
},
store: this.$store
})
infoWindow.$mount("#info-window")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 添加Popup对象
const popup = new mapboxgl.Popup({
anchor: "bottom",
offset: offset || [1, -15],
className: "popup"
});
popup.on("close", function(p) {
if (p && p.target && p.target._vue) {
p.target._vue.$destroy();
}
});
const dom = document.createElement("div");
dom.className = "popup-content-wrapper";

popup.setLngLat(coordinates).setDOMContent(dom).addTo(map);
// 渲染局部Vue组件(mappopupwrapper)
popup._vue = new Vue({
render: h =>
h(MapPopupWrapper, {
props: {
width: "700px",
type: "resource",
target: {
feature
}
}
})
}).$mount(dom);

options.preserveDrawingBuffer

If true , the map’s canvas can be exported to a PNG using map.getCanvas().toDataURL() . This is false by default as a performance optimization.

1
map.getCanvas().toDataURL()

queryRenderedFeatures

Returns an array of GeoJSON Feature objects representing visible features that satisfy the query parameters.

https://docs.mapbox.com/mapbox-gl-js/api/map/#map#queryrenderedfeatures

1
2
3
4
5
// Find all features within a static bounding box
var features = map.queryRenderedFeatures(
[[10, 20], [30, 50]],
{ layers: ['my-layer-name'] }
);
1
2
3
4
5
6
7
// Find all features within a bounding box around a point
var width = 10;
var height = 20;
var features = map.queryRenderedFeatures([
[point.x - width / 2, point.y - height / 2],
[point.x + width / 2, point.y + height / 2]
], { layers: ['my-layer-name'] });
1
2
// Query all rendered features from a single layer
var features = map.queryRenderedFeatures({ layers: ['my-layer-name'] });

querySourceFeatures

Returns an array of GeoJSON Feature objects representing features within the specified vector tile or GeoJSON source that satisfy the query parameters.

https://docs.mapbox.com/mapbox-gl-js/api/map/#map#querysourcefeatures

1
2
3
4
// Find all features in one source layer in a vector source
var features = map.querySourceFeatures('your-source-id', {
sourceLayer: 'your-source-layer'
});

updateImage

1
2
3
// If an image with the ID 'cat' already exists in the style's sprite,
// replace that image with a new image, 'other-cat-icon.png'.
if (map.hasImage('cat')) map.updateImage('cat', './other-cat-icon.png');
1
2
3
4
5
6
7
8
"icon-color": [
"case",
["boolean", ["feature-state", "hover"], false],
"#F89806",
["boolean", ["==", ["get", "state"], 0], false],
"#2363F8",
["get", "color"]
],

https://stackoverflow.com/questions/17964757/how-to-prune-delete-nodes-in-nested-tree-like-json

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
var a =  [
{
"label": "node1",
"children": [
{
"label": "Human"
},
{
"label": "Chimpanzee"
}
]
},
{
"label": "node2",
"children": [
{
"label": "node3",
"children": [
{
"label": "Rat"
},
{
"label": "Mouse"
}
]
},
{
"label": "BigRat"
}
]
}
]

function prune(array, label) {
for (var i = 0; i < array.length; ++i) {
var obj = array[i];
if (obj.label === label) {
// splice out 1 element starting at position i
array.splice(i, 1);
return true;
}
if (obj.children) {
if (prune(obj.children, label)) {
if (obj.children.length === 0) {
// delete children property when empty
delete obj.children;

// or, to delete this parent altogether
// as a result of it having no more children
// do this instead
array.splice(i, 1);
}
return true;
}
}
}
}

var wasItPruned = prune(tree, "node3");

简单说,就是允许碰撞

1
2
3
4
5
"icon-ignore-placement": true, //  不管下面
"icon-allow-overlap": true, // 允许被覆盖

"text-ignore-placement": true,
"text-allow-overlap": true,

polygon 多维数组是 “挖洞”

1
2
3
4
5
6
7
8
9
10
11
12
13
var aa =  { "type": "Polygon",
"coordinates": [

[ [108.9093384209429, 34.25000258545077],[108.90846464854332, 34.24677914297165],[108.91640950499936, 34.24612373914805],[108.91687875313949, 34.249801959853556],[108.9093384209429, 34.25000258545077]],

[ [108.91183029038228, 34.24663201194514] ,[108.91448396952353, 34.24651163182365], [108.91482376990217, 34.247608422127456],[108.91183029038228, 34.24663201194514]],

[[108.91026413410287, 34.24909755966851],[108.90994051469443, 34.24858930176197],[108.9122058505489, 34.248442173900116],[108.91243238413387, 34.24909755966851]]

]
}

test.map.getSource('temp_polygon').setData(aa)

MultiPolygon

最外面多一层

1
2
3
4
5
6
7
8
9
10
11
12
var aa =  { "type": "MultiPolygon",
"coordinates": [[

[ [108.9093384209429, 34.25000258545077],[108.90846464854332, 34.24677914297165],[108.91640950499936, 34.24612373914805],[108.91687875313949, 34.249801959853556],[108.9093384209429, 34.25000258545077]],

[ [108.91183029038228, 34.24663201194514] ,[108.91448396952353, 34.24651163182365], [108.91482376990217, 34.247608422127456],[108.91183029038228, 34.24663201194514]],


[[108.91026413410287, 34.24909755966851],[108.90994051469443, 34.24858930176197],[108.9122058505489, 34.248442173900116],[108.91243238413387, 34.24909755966851]]

]]
}

test.map.getSource(‘temp_polygon’).setData(aa)

多个 polygon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var aa = {
"type": "MultiPolygon",
"coordinates": [
[

[[108.9093384209429, 34.25000258545077], [108.90846464854332, 34.24677914297165], [108.91640950499936, 34.24612373914805], [108.91687875313949, 34.249801959853556], [108.9093384209429, 34.25000258545077]],
],
[
[[108.91183029038228, 34.24663201194514], [108.91448396952353, 34.24651163182365], [108.91482376990217, 34.247608422127456], [108.91183029038228, 34.24663201194514]],
],
[
[[108.91026413410287, 34.24909755966851], [108.90994051469443, 34.24858930176197], [108.9122058505489, 34.248442173900116], [108.91243238413387, 34.24909755966851]]
]
],
}

test.map.getSource('temp_polygon').setData(aa)

(从世界中)只显示 xxx

1
2
3
4
5
6
7
8
9
10
11
12
var aa =  {
"type": "Polygon",
"coordinates": [
[[-180, -90], [-180, 90], [180, 90], [180, -90], [-180, -90]],

要删掉的部分


]
}

test.map.getSource('temp_polygon').setData(aa)