終於來到鐵人賽的最後一哩路了, 重新將p5.js又學了一遍,不過觀念上更加融會貫通了。
今天來整理一下, 網頁配置與對齊排列的操作
在網頁的配置中常常會有需要對齊操作的需求,
首先要先來釐清一些觀念,這樣才能正確進行對齊的操作
「對齊」基本上,要先空出空間才有對齊的空間。
以div為例,沒有特別設定width的話,就是以整個100% width為寬的大小
但是高的部份,會以內容的高為準,所以處理水平置中,可以用 text-align: center; 來完成,
例如: 這是文宇的對齊
<style>
#a1 {
text-align: center;
}
</style>
<body>
<div id="a1">align</div>
</body>
但是垂直置中,就要用不同的方式處理了。
在p5.js提供一個指令是center(),就是元件置中,置中的範圍是以元件的上層元件的大小為準
center(): 同時水平,垂直置中
center('horizontal'): 只有水平置中
center('vertical'): 只有垂直置中
<style>
html, body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
background-color: black;
}
#a1 {
background-color: rgb(49, 49, 32);
}
</style>
<body>
<div id="a1">
<img id="img1" src="assets/multicore_logo_300.png">
</div>
</body>
<script>
function setup() {
noCanvas();
select("#a1").size(500, 500);
select("#img1").center(); //-- 以div為範圍置中
select("#a1").center(); //-- 以body為範圍置中
console.log(select("body"));
console.log(select("body").position());
console.log(select("#a1"));
console.log(select("#a1").position());
console.log(select("#img1"));
console.log(select("#img1").position());
}
</script>
結果如下
不過,select("#a1").center(); 只會在執行center()時置中,若有因為視窗大小改變時,
並不會自動置中,需要在windowResized()的事件觸發時,再次執行 center()指令
function windowResized() {
select("#a1").center();
//-- 只需將會受windowResized()影響的元件再次執行 center()指令即可。
}
雖然有center()可以用,不過,還是建議以CSS的方式為主要方法。
在網頁中的座標系統,一般可分相對座標,及絕對座標
position: static;
position: relative;
position: absolute; 絕對座標
position: fixed; 絕對座標
position: sticky; 絕對座標
對網頁內容的設計來說,最大的難題就是動態調整內容的縮放比例,置中對齊,以及不同尺寸,不同方向的觀看調整。
因此對於座標及大小,以及排列的方式就顯得重要且複雜了。
一般來說,有3種主要的方案,
第1種是使用p5.js的套件,就是全部以Canvas為基準來配置
第2種是以絕對關係為原則,就是使用 CSS calc()的功能
第3種是以相對關係為原則,就是使用 CSS Flex系統
對p5.js的說,可以完全使用p5.Element的功能來操作
不過以下這幾個指令,
style(), class(), center(), position(), size()
在遇到需要動態調整內容時,就要在事件觸發時,重新再執行一次,
以根據新的視窗大小,重新計算受影響的參數。
因此,可能的解決方法,就以基本上用CSS來設定成不同的樣式的class,再用p5.js的
class(), addClass(), removeClass(), hasClass(), toggleClass()
來對css 的class進行操作切換。
這個是p5.js的方法,要自行處理置中座標的計算,在windowResized()時,也要重新計算
let can;
let img;
let px = 0;
let py = 0;
function setup() {
can = createCanvas(400, 400);
can.id("can1");
can.center();
background("lightyellow");
img = createImg("assets/multicore_logo_300.png", 'img', "", () => {
px = (width-img.elt.width)/2+can.position().x;
py = (height-img.elt.height)/2+can.position().y;
img.position(px, py);
});
img.mouseClicked(() => {
alert("OK");
});
}
function draw(){
}
function windowResized() {
can.center();
px = (width-img.elt.width)/2 + can.position().x;
py = (height-img.elt.height)/2 + can.position().y;
img.position(px, py);
}
這是使用到CSS 的Calc()的功能
CSS
#can1 {
position: absolute;
left: calc((100vw - 400px)/2);
top: calc((100vh - 400px)/2);
}
#img1 {
position: absolute;
left: calc((100vw - 300px)/2);
top: calc((100vh - 300px)/2);
}
JS
let can;
let img;
function setup() {
can = createCanvas(400, 400);
can.id("can1");
background("lightyellow");
img = createImg("assets/multicore_logo_300.png", 'img');
img.id("img1");
}
這是使用flex的方法
HTML
<body>
<div id="d1"></div>
<div id="d2"></div>
</body>
CSS
html, body {
margin: 0;
padding: 0;
width: 100vw;
height: 100vh;
background-color: black;
display: flex;
justify-content: center;
align-items: center;
}
#d1 {
position: absolute;
z-index: 5;
}
#d2 {
position: absolute;
z-index: 10;
}
JS
let can;
let img;
function setup() {
can = createCanvas(400, 400);
can.id("can1");
can.parent("d1");
background("lightyellow");
img = createImg("assets/multicore_logo_300.png", 'img');
img.id("img1");
img.parent("d2");
}
執行結果
以上的示範可以看出,格式(HTML),樣式(CSS),程式(JS),三者之間互相搭配才能找出最佳的解決方案。
連最後一篇都還是寫點分享,可以知道鐵人賽雖然很辛苦,但是一旦起跑了,就會一直跑下去。
有句話說「習慣成自然」,但在這之前還有一句話,「勉強成習慣」,
一開始總是比較「勉強」,「勉強」久了就養成「習慣」,
最後自然而然成為生活的一部份。
謝謝大家對於這個「從新開始學習p5.js畫出一片天」系到的關注。
參考資料
position
https://developer.mozilla.org/en-US/docs/Web/CSS/position
CSS Flex Container
https://www.w3schools.com/css/css3_flexbox_container.asp
CSS calc() Function
https://www.w3schools.com/cssref/func_calc.asp
Get started with Bootstrap
https://getbootstrap.com/docs/5.2/getting-started/introduction/