d3js scales深入理解

来源:https://www.cnblogs.com/feiquan/archive/2019/04/23/10755868.html
-Advertisement-
Play Games

轉自:https://www.cnblogs.com/kidsitcn/p/7182274.html 比例尺函數是這樣的javascript函數: 接收通常是數字,日期,類別等data輸入並且: 返回一個代表可視化元素的值,比如坐標,顏色,長度或者半徑等 比例尺通常用於變換(或者說映射)抽象的數據值 ...


轉自:https://www.cnblogs.com/kidsitcn/p/7182274.html

比例尺函數是這樣的javascript函數:

  • 接收通常是數字,日期,類別等data輸入並且:
  • 返回一個代表可視化元素的值,比如坐標,顏色,長度或者半徑等

比例尺通常用於變換(或者說映射)抽象的數據值到可視量化變數(比如位置,長度,顏色等)

比如,假設我們有以下數組數據:

[ 0, 2, 3, 5, 7.5, 9, 10 ]

我們可以這樣創建一個比例尺函數:

var myScale = d3.scaleLinear()
  .domain([0, 10])
  .range([0, 600]);

d3將創建一個myScale函數用於接收[0,10]之間的數據輸入(domain)映射為[0,600]像素的位置數據(range)

我們可以使用myScale函數來計算對應數據的positions數據:

myScale(0);   // returns 0
myScale(2);   // returns 120
myScale(3);   // returns 180
...
myScale(10);  // returns 

如上面所說,比例尺主要用於將抽象數據映射為可視的量化元素,比如位置,長度,半徑,顏色等。比如,他們可以這樣應用

  • 將抽象數據映射為0到500的長度值以便在bar chart中使用
  • 將抽象數據映射為0到200之間的位置數據值以便作為line charts中點的坐標來使用
  • 將百分比變化數據(+4%,+10%,-5%等)映射為顏色的對應變化(比如使用紅色表示為正值,正的越多越紅,負值為綠色,負的越多綠色飽和度越高)
  • 將日期數據映射為x軸上的位置

Constructing scales

這部分我們集中使用線性比例尺linear scale作為例子探討scale的相關知識,在後面再探討其他類型的比例尺

var myScale = d3.scaleLinear();

 

註意:v4和v3的聲明方式是不同的 d3.scaleLinear() in v4 and d3.scale.linear() in 
myScale
  .domain([0, 100])
  .range([0, 800]);

通過上面的代碼,myScale就成為有特定意義的比例尺函數了。現在myScale可以接收任何在0,100之間的domain,而映射到0到800的range裡面。我們可以像下麵一樣來調用這個比例尺函數:

myScale(0);    // returns 0
myScale(50);   // returns 400
myScale(100);  // returns 800

D3 scale types

D3大約有12種不同的比例尺類型(scaleLinear, scalePow, scaleQuantise, scaleOrdinal etc.) ,而總體來說我們可以分為3類

下麵我們一個一個地來仔細學習一下

Scales with continuous input and continuous output(連續性輸入連續性輸出)

scaleLinear

線性比例尺可能是應用最為廣泛的比例尺類型了,因為他們最適合將數據轉化為位置和長度。因此往往也以線性比例尺為例去講解和學習比例次的知識

他們使用一個線性函數(y=m*x+b)來表達(domain)和(range)之間的數學函數關係

複製代碼
var linearScale = d3.scaleLinear()
  .domain([0, 10])
  .range([0, 600]);

linearScale(0);   // returns 0
linearScale(5);   // returns 300
linearScale(10);  // returns 600
複製代碼

典型地,他們被用於將抽象數據轉換為位置,長度等可視元素。因此當我們創bar chart,line chart,或者其他很多圖標類型時,我們可以使用它。

除了位置長度作為range,也可以使用顏色值哦(實際上顏色也可以作為連續性數據的):

複製代碼
var linearScale = d3.scaleLinear()
  .domain([0, 10])
  .range(['yellow', 'red']);

linearScale(0);   // returns "rgb(255, 255, 0)"
linearScale(5);   // returns "rgb(255, 128, 0)"
linearScale(10);  // returns "rgb(255, 0, 0)"
複製代碼

這個特性常常被用於等值線圖(choropleth),當然我們也可以使用scaleQuantize,scaleQuantile和scaleThrshold.

scalePow

scalePow這個比例次使用y = m * x^k + b這個數學函數來表達domain和range之間的數學函數關係。指數k使用.exponent()來設定:

var powerScale = d3.scalePow() .exponent(0.5) .domain([0, 100]) .range([0, 30]); 
powerScale(0); // returns 0 
powerScale(50); // returns 21.21... 
powerScale(100); // returns 30

scaleSqrt

scaleSqrt 比例次是一種scalePow的特殊形式(k=0.5)通常用於通過面積來表徵圓(而不用半徑)(當使用圓的大小來表達數據值的大小時,通常最佳實踐是使用和數據等比例的面積而非半徑來表達)

複製代碼
var sqrtScale = d3.scaleSqrt()
  .domain([0, 100])
  .range([0, 30]);

sqrtScale(0);   // returns 0
sqrtScale(50);  // returns 21.21...
sqrtScale(100); // returns 30
複製代碼

我們可以看到這個例子和上面的例子輸出是一樣的。

scaleLog

Log scales 使用數學對數函數(y = m * log(x) + b)來映射domain和range.如果數據之間有指數關係的話,這個log比例尺最適合

複製代碼
var logScale = d3.scaleLog()
  .domain([10, 100000])
  .range([0, 600]);

logScale(10);     // returns 0
logScale(100);    // returns 150
logScale(1000);   // returns 300
logScale(100000); // returns 600
複製代碼

scaleTime

scaleTime和scaleLinear是類似的,唯一的區別是domain用於代表date的數組。(通常對於時間序列非常有用)

timeScale = d3.scaleTime() .domain([new Date(2016, 0, 1), new Date(2017, 0, 1)]) .range([0, 700]); 
timeScale(new Date(2016, 0, 1)); // returns 0 
timeScale(new Date(2016, 6, 1)); // returns 348.00... 
timeScale(new Date(2017, 0, 1)); // returns 700

scaleSequential

scaleSequential用於將連續性的數據映射為由預定義或者定製的插值函數決定的range.(一個插值函數是一個接受0到1之間的數值而輸出一個在兩個數字,兩個顏色值或者兩個字元串之間的插值的函數)

D3提供了很多預定義的插值函數,其中包含著很多顏色相關的插值函數。例如,我們可以使用d3.interpolateRainbow來創建著名的彩虹色系圖:

複製代碼
var sequentialScale = d3.scaleSequential()
  .domain([0, 100])
  .interpolator(d3.interpolateRainbow);

sequentialScale(0);   // returns 'rgb(110, 64, 170)'
sequentialScale(50);  // returns 'rgb(175, 240, 91)'
sequentialScale(100); // returns 'rgb(110, 64, 170)'
複製代碼

需要註意的是插值函數決定了output range,因此你不需要對這個sequential scale來指定range

下麵的列子展示由d3提供的其他顏色插值範圍函數:

複製代碼
var linearScale = d3.scaleLinear()
    .domain([0, 100])
    .range([0, 600]);

var sequentialScale = d3.scaleSequential()
    .domain([0, 100]);

var interpolators = [
    'interpolateViridis',
    'interpolateInferno',
    'interpolateMagma',
    'interpolatePlasma',
    'interpolateWarm',
    'interpolateCool',
    'interpolateRainbow',
    'interpolateCubehelixDefault'
];

var myData = d3.range(0, 100, 2);

function dots(d) {
    sequentialScale
        .interpolator(d3[d]);

    d3.select(this)
        .append('text')
        .attr('y', -10)
        .text(d);

    d3.select(this)
        .selectAll('rect')
        .data(myData)
        .enter()
        .append('rect')
        .attr('x', function(d) {
            return linearScale(d);
        })
        .attr('width', 11)
        .attr('height', 30)
        .style('fill', function(d) {
            return sequentialScale(d);
        });
}

d3.select('#wrapper')
    .selectAll('g.interpolator')
    .data(interpolators)
    .enter()
    .append('g')
    .classed('interpolator', true)
    .attr('transform', function(d, i) {
        return 'translate(0, ' + (i * 70) + ')';
    })
    .each(dots);
複製代碼

 

除了d3定義的這些顏色插值範圍函數,也有一個 d3-scale-chromatic plugin, 提供著名的 ColorBrewer colour schemes.

Clamping

預設情況下 scaleLinearscalePowscaleSqrtscaleLogscaleTime and scaleSequential 允許輸入值在domain範圍之外比如:

複製代碼
var linearScale = d3.scaleLinear()

  .domain([0, 10])
  .range([0, 100]);

linearScale(20);  // returns 200
linearScale(-10); // returns -100
複製代碼

在這種情況下scale函數就使用外推演算法來返回domain範圍之外的輸入值對應的返回值。

如果我們希望比例尺函數嚴格限制輸入值必須在domain規定的範圍內,我們則可以使用.clamp()調用

linearScale.clamp(true);

linearScale(20);  // returns 100
linearScale(-10); // returns 0

我們也可以隨時通過clamp(false)來關閉這個功能

Nice

如果domain是由實際數據自動算出來的,比如使用d3.extent,d3.min/max來定義,那麼起始和結束數據可能並不是整數。這本身並不是什麼問題,但是如果使用這個比例尺函數來定義一個坐標軸,則顯得很不整潔

複製代碼
var data = [0.243, 0.584, 0.987, 0.153, 0.433];
var extent = d3.extent(data);

var linearScale = d3.scaleLinear()
  .domain(extent)
  .range([0, 100]);
複製代碼

我們通過使用.nice()函數,那麼就將domain做了nice處理:

linearScale.nice();

需要註意的是.nice()函數必須在domain更新後每次都必須重新調用!

Multiple segments

The domain and range of scaleLinearscalePowscaleSqrtscaleLog and scaleTime usually consists of two values, but if we provide 3 or more values the scale function is subdivided into multiple segments:

通常scaleLinear,scalePow,scaleSqrt,scaleLog和scaleTime比例尺的domain和range都只包含兩個數值:起始和結束值來定義,但是如果我們提供3個甚至更多的值,那麼比例尺函數就將被劃分為幾個段segments:

複製代碼
var linearScale = d3.scaleLinear()
  .domain([-10, 0, 10])
  .range(['red', '#ddd', 'blue']);

linearScale(-10);  // returns "rgb(255, 0, 0)"
linearScale(0);    // returns "rgb(221, 221, 221)"
linearScale(5);    // returns "rgb(128, 128, 255)"
複製代碼

看看一個例子效果:

複製代碼
var xScale = d3.scaleLinear()
    .domain([-10, 10])
    .range([0, 600]);

var linearScale = d3.scaleLinear()
    .domain([-10, 0, 10])
    .range(['red', '#ddd', 'blue']);

var myData = [-10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10];

d3.select('#wrapper')
    .selectAll('circle')
    .data(myData)
    .enter()
    .append('circle')
    .attr('r', 10)
    .attr('cx', function(d) {
        return xScale(d);
    })
    .style('fill', function(d) {
        return linearScale(d);
    });
複製代碼

典型地,多segment的比例尺通常用於區分正負值(正如上面例子所示)。只要domain和range的段數是相同的,我們可以使用任意多segments的比例尺.

Inversion

 .invert() 方法接受一個range輸出來反算對應的input domain

複製代碼
var linearScale = d3.scaleLinear()
  .domain([0, 10])
  .range([0, 100]);

linearScale.invert(50);   // returns 5
linearScale.invert(100);  // returns 10
複製代碼

A common use case is when we want to convert a user’s click along an axis into a domain value:

這個方法的典型使用場景是我們將用戶沿著某坐標軸點擊坐標反轉為domain值:

複製代碼
var width = 600;

var linearScale = d3.scaleLinear()
  .domain([-50, 50])
  .range([0, width])
  .nice();

var clickArea = d3.select('.click-area').node();

function doClick() {
    var pos = d3.mouse(clickArea);
    var xPos = pos[0];
    var value = linearScale.invert(xPos);
    d3.select('.info')
        .text('You clicked ' + value.toFixed(2));
}

// Construct axis
var axis = d3.axisBottom(linearScale);
d3.select('.axis')
    .call(axis);

// Update click area size
d3.select('.click-area')
    .attr('width', width)
    .attr('height', 40)
    .on('click', doClick);
複製代碼

Scales with continuous input and discrete output

scaleQuantize

scaleQuantize 接受連續性的range輸入而輸出由range定義的離散輸出

複製代碼
var quantizeScale = d3.scaleQuantize()
  .domain([0, 100])
  .range(['lightblue', 'orange', 'lightgreen', 'pink']);

quantizeScale(10);   // returns 'lightblue'
quantizeScale(30);  // returns 'orange'
quantizeScale(90);  // returns 'pink'
複製代碼
Each range value is mapped to an equal sized chunk in the domain so in the example above:
每一個range值都被映射為一個domain的等分量值區間
  • 0 ≤ u < 25 is mapped to ‘lightblue’
  • 25 ≤ u < 50 is mapped to ‘orange’
  • 50 ≤ u < 75 is mapped to ‘lightgreen’
  • 75 ≤ u < 100 is mapped to ‘pink’

u 是輸入domain值

註意由於我們使用了.clamp指示,因此quantizeScale(-10)返回'lightblue',而quantizeScale(110)返回'pink'

scaleQuantile

scaleQuantile 將輸入的連續性domain值映射為離散的值。domain是由數組來定義:

複製代碼
var myData = [0, 5, 7, 10, 20, 30, 35, 40, 60, 62, 65, 70, 80, 90, 100];

var quantileScale = d3.scaleQuantile()
  .domain(myData)
  .range(['lightblue', 'orange', 'lightgreen']);

quantileScale(0);   // returns 'lightblue'
quantileScale(20);  // returns 'lightblue'
quantileScale(30);  // returns 'orange'
quantileScale(65);  // returns 'lightgreen'
複製代碼

複製代碼
var myData = [0, 5, 7, 10, 20, 30, 35, 40, 60, 62, 65, 70, 80, 90, 100];

var linearScale = d3.scaleLinear()
    .domain([0, 100])
    .range([0, 600]);

var quantileScale = d3.scaleQuantile()
    .domain(myData)
    .range(['lightblue', 'orange', 'lightgreen']);

d3.select('#wrapper')
    .selectAll('circle')
    .data(myData)
    .enter()
    .append('circle')
    .attr('r', 3)
    .attr('cx', function(d) {
        return linearScale(d);
    })
    .style('fill', function(d) {
        return quantileScale(d);
    });
複製代碼

排好序的domain數組被均分為n個子範圍,這裡n是range數值的個數

這樣在上面的例子中domain數組就被均分為3個groups:

  • the first 5 values are mapped to ‘lightblue’
  • the next 5 values to ‘orange’ and
  • the last 5 values to ‘lightgreen’.

具體的domain均分點可以通過.quantiles()來訪問

quantileScale.quantiles();  // returns [26.66..., 63]

如果range包含4個值,那麼quantileScale將這樣計算quantiles: 最低25%的數據被映射為range[0], 下一個25%則映射為range[1],以此類推。

scaleThreshold

scaleThreshold 映射連續的輸入domain為由range來定義的離散值. 如果range值有n個,則將會有n-1個切分點

下麵的例子我們在050和100處切分

  • u < 0 is mapped to ‘#ccc’
  • 0 ≤ u < 50 to ‘lightblue’
  • 50 ≤ u < 100 to ‘orange’
  • u ≥ 100 to ‘#ccc’

這裡u 是input value.

複製代碼
var thresholdScale = d3.scaleThreshold()
  .domain([0, 50, 100])
  .range(['#ccc', 'lightblue', 'orange', '#ccc']);

thresholdScale(-10);  // returns '#ccc'
thresholdScale(20);   // returns 'lightblue'
thresholdScale(70);   // returns 'orange'
thresholdScale(110);  // returns '#ccc'
複製代碼

詳細代碼如下:

複製代碼
var linearScale = d3.scaleLinear()
    .domain([-10, 110])
    .range([0, 600]);

var thresholdScale = d3.scaleThreshold()
    .domain([0, 50, 100])
    .range(['#ccc', 'lightblue', 'orange', '#ccc']);

var myData = d3.range(-10, 110, 2);

d3.select('#wrapper')
    .selectAll('rect')
    .data(myData)
    .enter()
    .append('rect')
    .attr('x', function(d) {
        return linearScale(d);
    })
    .attr('width', 9)
    .attr('height', 30)
    .style('fill', function(d) {
        return thresholdScale(d);
    });
複製代碼

Scales with discrete input and discrete output

scaleOrdinal

scaleOrdinal 將離散的domain values array映射為離散的range values array. domain input array指定可能的輸入value,而range array則定義對應的可能的輸出value.如果range array比domain array要短,則range array會重覆迴圈

複製代碼
var myData = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

var ordinalScale = d3.scaleOrdinal()
  .domain(myData)
  .range(['black', '#ccc', '#ccc']);

ordinalScale('Jan');  // returns 'black';
ordinalScale('Feb');  // returns '#ccc';
ordinalScale('Mar');  // returns '#ccc';
ordinalScale('Apr');  // returns 'black';
複製代碼

完整代碼如下:

複製代碼
var myData = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

var linearScale = d3.scaleLinear()
    .domain([0, 11])
    .range([0, 600]);

var ordinalScale = d3.scaleOrdinal()
    .domain(myData)
    .range(['black', '#ccc', '#ccc']);

d3.select('#wrapper')
    .selectAll('text')
    .data(myData)
    .enter()
    .append('text')
    .attr('x', function(d, i) {
        return linearScale(i);
    })
    .text(function(d) {
        return d;
    })
    .style('fill', function(d) {
        return ordinalScale(d);
    });
複製代碼

By default if a value that’s not in the domain is used as input, the scale will implicitly add the value to the domain:

預設情況下如果輸入值不在domain範圍內,scale會隱含地添加這個值到domain中去。

ordinalScale('Monday');  // returns 'black';

如果這不是我們想要的行為,我們可以使用.unknown()函數來設定一個unknown values

ordinalScale.unknown('Not a month');
ordinalScale('Tuesday'); // returns 'Not a month'

D3也提供一些預定義好的color scheme

var ordinalScale = d3.scaleOrdinal()
  .domain(myData)
  .range(d3.schemePaired);
複製代碼
var myData = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']

var linearScale = d3.scaleLinear()
  .domain([0, 11])
  .range([0, 600]);

var ordinalScale = d3.scaleOrdinal()
  .domain(myData)
  .range(d3.schemePaired);

d3.select('#wrapper')
  .selectAll('text')
  .data(myData)
  .enter()
  .append('text')
  .attr('x', function(d, i) {
    return linearScale(i);
  })
  .text(function(d) {
    return d;
  })
  .style('fill', function(d) {
    return ordinalScale(d);
  });
複製代碼

(Note that the Brewer colour schemes are defined within a separate file d3-scale-chromatic.js.)

scaleBand

當創建一個bar chart時,scaleBand可以幫助我們來決定bar的幾何形狀,並且已經考慮好了各個bar之間的padding值。

輸入的domain通過一個數值數組來指定(每個值都對應一個band)並且range通過bands的最小和最大範圍來定義(也就是bar chart的整個寬度)

scaleBand會將range劃分為n個bands(n是domain數組的數值個數)並且在考慮padding的情況下計算出每個band的位置和寬度.

複製代碼
var bandScale = d3.scaleBand()
  .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
  .range([0, 200]);

bandScale('Mon'); // returns 0
bandScale('Tue'); // returns 40
bandScale('Fri'); // returns 160
複製代碼

每個band的寬度可以使用.bandWidth()來訪問。

bandScale.bandwidth();  // returns 40

有兩種padding可以被配置:

  • paddingInner which specifies (as a percentage of the band width) the amount of padding between each band
  • paddingOuter which specifies (as a percentage of the band width) the amount of padding before the first band and after the last band

我們在上面的例子中添加一點inner padding

bandScale.paddingInner(0.05);

bandScale.bandWidth();  // returns 38.38...
bandScale('Mon');       // returns 0
bandScale('Tue');       // returns 40.40...

Putting this all together we can create this bar chart:

上面加起來我們可以得到下麵的圖表:

複製代碼
var myData = [
    {day : 'Mon', value: 10},
    {day : 'Tue', value: 40},
    {day : 'Wed', value: 30},
    {day : 'Thu', value: 60},
    {day : 'Fri', value: 30}
];

var bandScale = d3.scaleBand()
    .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
    .range([0, 200])
    .paddingInner(0.05);

d3.select('#wrapper')
    .selectAll('rect')
    .data(myData)
    .enter()
    .append('rect')
    .attr('y', function(d) {
        return bandScale(d.day);
    })
    .attr('height', bandScale.bandwidth())
    .attr('width', function(d) {
        return d.value;
    });
複製代碼

 

scalePoint

scalePoint 將離散的輸入數值映射為在range內等距的點:

複製代碼
var pointScale = d3.scalePoint()
  .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
  .range([0, 500]);

pointScale('Mon');  // returns 0
pointScale('Tue');  // returns 125
pointScale('Fri');  // returns 500
複製代碼

完整代碼:

複製代碼
var myData = [
    {day : 'Mon', value: 10},
    {day : 'Tue', value: 40},
    {day : 'Wed', value: 30},
    {day : 'Thu', value: 60},
    {day : 'Fri', value: 30}
];

var pointScale = d3.scalePoint()
    .domain(['Mon', 'Tue', 'Wed', 'Thu', 'Fri'])
    .range([0, 600]);

d3.select('#wrapper')
    .selectAll('circle')
    .data(myData)
    .enter()
    .append('circle')
    .attr('cx', function(d) {
        return pointScale(d.day);
    })
    .attr('r', 4);
複製代碼

 

點之間的距離可以通過.step()來訪問:

pointScale.step();  // returns 125

outside padding可以通過和padding to point spacing的比例來指定。比如,如果希望設定outside padding為point spacing的1/4,那麼可以這樣設置:

pointScale.padding(0.25);

pointScale('Mon');  // returns 27.77...
pointScale.step();  // returns 111.11...

 

參考閱讀

ColorBrewer schemes for D3

Mike Bostock on d3-scale

積小流以匯江海,細微做起
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • <!doctype html> <html> <head> <meta charset="urtf-8"> <title>通過js改變class名字改變樣式</title> <style> .tao { /*初始樣式*/ border-radius:35px; width:100px; height ...
  • 1.jQuery對象 jQuery包裝集對象 獲得mydiv的Jquery對象: var divJquery = $("#mydiv"); 2.基礎選擇器 1、ID選擇器格式:$("#id屬性值") 獲取指定id值的對象(只會獲取到第一個id的值)2、類選擇器格式:$(".class屬性值")獲取所 ...
  • 註: 依賴第三方插件 clipboard 一、安裝插件 二、全局註入(main.js) 三、使用 四、效果圖 ...
  • 最近公司有需求要做一些可視化的功能。之前一直都是用Echarts做的,但是Echarts現在滿足不了我們的需求,經過多方請教,查找發現只有D3可以滿足我們的需求,而且可以完美的適用到react框架中。第一次接觸到D3,發現這些圖標的可交互性非常豐富,而且動畫流暢簡潔。 所以,打算學習D3並且應用到項 ...
  • 今天練習一個小demo, 從本地讀取圖片, 然後實現類似淘寶放大鏡的效果, 再加兩個需求 1 .可以調節縮放比例,預設放大兩倍 2 . 圖片寬高自適應, 不固定寬高 話不多說先看效果: 原理:1, 右側放大區域的大小等於左側半透明滑塊大小乘以縮放倍數 2, 右側放大區域圖片的原始尺寸要和 左側圖片一 ...
  • <html><body> <h3>js控制文件上傳數量</h3> <form action="" enctype="multipart/form-data"> <input type="file" name="file" multiple="multiple" onchange="fileCount ...
  • 一、什麼是小程式? 基於微信的可以為用戶提供一些服務的web項目,利用微信提供的介面可以讓所有開發者使用到微信的原生能力,去完成一些之前做不到或者難以做到的事情。 二、小程式開發工具以及語言? 小程式需要用到微信提供的小程式開發工具,​小程式的主要開發語言是 JavaScript 。 三、小程式與普 ...
  • 項目中經常遇到要選擇城市。用到三級聯動的方式 微信小程式的 組件 是三級聯動的,但是無法自定義,這讓我們心痛不已,值得我們欣慰的 picker view 組件是可以自定義添加多個選項,但還是無法聯動。既然這樣那就自己寫一個聯動。 做到如下圖所示: 分為動態獲取地址 引用靜態文件獲取地址 <! mor ...
一周排行
    -Advertisement-
    Play Games
  • 示例項目結構 在 Visual Studio 中創建一個 WinForms 應用程式後,項目結構如下所示: MyWinFormsApp/ │ ├───Properties/ │ └───Settings.settings │ ├───bin/ │ ├───Debug/ │ └───Release/ ...
  • [STAThread] 特性用於需要與 COM 組件交互的應用程式,尤其是依賴單線程模型(如 Windows Forms 應用程式)的組件。在 STA 模式下,線程擁有自己的消息迴圈,這對於處理用戶界面和某些 COM 組件是必要的。 [STAThread] static void Main(stri ...
  • 在WinForm中使用全局異常捕獲處理 在WinForm應用程式中,全局異常捕獲是確保程式穩定性的關鍵。通過在Program類的Main方法中設置全局異常處理,可以有效地捕獲並處理未預見的異常,從而避免程式崩潰。 註冊全局異常事件 [STAThread] static void Main() { / ...
  • 前言 給大家推薦一款開源的 Winform 控制項庫,可以幫助我們開發更加美觀、漂亮的 WinForm 界面。 項目介紹 SunnyUI.NET 是一個基於 .NET Framework 4.0+、.NET 6、.NET 7 和 .NET 8 的 WinForm 開源控制項庫,同時也提供了工具類庫、擴展 ...
  • 說明 該文章是屬於OverallAuth2.0系列文章,每周更新一篇該系列文章(從0到1完成系統開發)。 該系統文章,我會儘量說的非常詳細,做到不管新手、老手都能看懂。 說明:OverallAuth2.0 是一個簡單、易懂、功能強大的許可權+可視化流程管理系統。 有興趣的朋友,請關註我吧(*^▽^*) ...
  • 一、下載安裝 1.下載git 必須先下載並安裝git,再TortoiseGit下載安裝 git安裝參考教程:https://blog.csdn.net/mukes/article/details/115693833 2.TortoiseGit下載與安裝 TortoiseGit,Git客戶端,32/6 ...
  • 前言 在項目開發過程中,理解數據結構和演算法如同掌握蓋房子的秘訣。演算法不僅能幫助我們編寫高效、優質的代碼,還能解決項目中遇到的各種難題。 給大家推薦一個支持C#的開源免費、新手友好的數據結構與演算法入門教程:Hello演算法。 項目介紹 《Hello Algo》是一本開源免費、新手友好的數據結構與演算法入門 ...
  • 1.生成單個Proto.bat內容 @rem Copyright 2016, Google Inc. @rem All rights reserved. @rem @rem Redistribution and use in source and binary forms, with or with ...
  • 一:背景 1. 講故事 前段時間有位朋友找到我,說他的窗體程式在客戶這邊出現了卡死,讓我幫忙看下怎麼回事?dump也生成了,既然有dump了那就上 windbg 分析吧。 二:WinDbg 分析 1. 為什麼會卡死 窗體程式的卡死,入口門檻很低,後續往下分析就不一定了,不管怎麼說先用 !clrsta ...
  • 前言 人工智慧時代,人臉識別技術已成為安全驗證、身份識別和用戶交互的關鍵工具。 給大家推薦一款.NET 開源提供了強大的人臉識別 API,工具不僅易於集成,還具備高效處理能力。 本文將介紹一款如何利用這些API,為我們的項目添加智能識別的亮點。 項目介紹 GitHub 上擁有 1.2k 星標的 C# ...