1. บทนำ
คอมโพเนนต์เว็บ
คอมโพเนนต์ของเว็บคือชุดมาตรฐานของเว็บที่ช่วยให้นักพัฒนาซอฟต์แวร์ขยาย HTML ด้วยองค์ประกอบที่กำหนดเอง ใน Codelab นี้ คุณจะได้กำหนดองค์ประกอบ <brick-viewer>
ซึ่งจะแสดงโมเดลตัวต่อได้
องค์ประกอบที่มีแสงสว่าง
เราจะใช้องค์ประกอบ "แสงสว่าง" เพื่อช่วยเรากำหนดองค์ประกอบที่กำหนดเอง <brick-viewer>
lit-element เป็นคลาสพื้นฐานขนาดเล็กที่เพิ่มน้ำตาลไวยากรณ์ลงในมาตรฐานคอมโพเนนต์เว็บ ซึ่งจะช่วยให้เราสร้างและใช้งานองค์ประกอบที่กำหนดเองได้โดยง่าย
เริ่มต้นใช้งาน
เราจะเขียนโค้ดในสภาพแวดล้อมออนไลน์ของ Stackblitz ดังนั้นให้เปิดลิงก์นี้ในหน้าต่างใหม่
stackblitz.com/edit/brick-viewer
มาเริ่มกันเลย
2. กำหนดองค์ประกอบที่กำหนดเอง
คำจำกัดความของชั้นเรียน
หากต้องการระบุองค์ประกอบที่กำหนดเอง ให้สร้างคลาสที่ขยาย LitElement
และตกแต่งด้วย @customElement
อาร์กิวเมนต์ของ @customElement
จะเป็นชื่อขององค์ประกอบที่กำหนดเอง
ใน brick-viewer.ts ให้ใส่:
@customElement('brick-viewer')
export class BrickViewer extends LitElement {
}
ตอนนี้องค์ประกอบ <brick-viewer></brick-viewer>
พร้อมใช้งานใน HTML แล้ว แต่หากลองใช้ ก็จะไม่แสดงผลใดๆ เรามาแก้ปัญหานั้นกันดีกว่า
วิธีแสดงผล
หากต้องการใช้มุมมองของคอมโพเนนต์ ให้กำหนดเมธอดที่ชื่อว่า Render เมธอดนี้ควรแสดงผลเทมเพลตลิเทอรัลที่ติดแท็กด้วยฟังก์ชัน html
ใส่ HTML ที่คุณต้องการในลิเทอรัลของเทมเพลตที่ติดแท็ก ส่วนนี้จะแสดงผลเมื่อคุณใช้ <brick-viewer>
เพิ่มเมธอด render
:
export class BrickViewer extends LitElement {
render() {
return html`<div>Brick viewer</div>`;
}
}
3. การระบุไฟล์ LDraw
กำหนดพร็อพเพอร์ตี้
คงจะดีไม่น้อยหากผู้ใช้ของ <brick-viewer>
สามารถระบุโมเดลตัวต่อที่จะแสดงโดยใช้แอตทริบิวต์ดังตัวอย่างต่อไปนี้
<brick-viewer src="path/to/model.ldraw"></brick-viewer>
เนื่องจากเรากำลังสร้างองค์ประกอบ HTML เราจึงใช้ประโยชน์จาก API แบบประกาศและกำหนดแอตทริบิวต์แหล่งที่มาได้ เช่นเดียวกับแท็ก <img>
หรือ <video>
เมื่อมีองค์ประกอบส่องสว่างจะช่วยให้ตกแต่งที่พักได้ง่ายดายพอๆ กับการตกแต่งที่พักระดับชั้นเรียนด้วย @property
ตัวเลือก type
ให้คุณระบุวิธีที่องค์ประกอบที่มีแสงสว่างเพียงพอจะแยกวิเคราะห์พร็อพเพอร์ตี้เพื่อใช้เป็นแอตทริบิวต์ HTML
กำหนดพร็อพเพอร์ตี้และแอตทริบิวต์ src
ดังนี้
export class BrickViewer extends LitElement {
@property({type: String})
src: string|null = null;
}
ตอนนี้ <brick-viewer>
มีแอตทริบิวต์ src
ที่เราตั้งค่าใน HTML ได้แล้ว ค่านี้สามารถอ่านได้จากภายในคลาส BrickViewer
ด้วยองค์ประกอบที่มีแสง
กำลังแสดงค่า
เราแสดงค่าของแอตทริบิวต์ src
ได้โดยใช้ค่านั้นในลิเทอรัลเทมเพลตของวิธีการแสดงผล แปลงค่าลงในลิเทอรัลเทมเพลตโดยใช้ไวยากรณ์ ${value}
export class BrickViewer extends LitElement {
render() {
return html`<div>Brick model: ${this.src}</div>`;
}
}
ตอนนี้ เราจะเห็นค่าของแอตทริบิวต์ src ในองค์ประกอบ <brick-viewer>
ในหน้าต่าง ลองใช้: เปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์และเปลี่ยนแอตทริบิวต์ src ด้วยตนเอง ลองใช้งาน...
...คุณสังเกตเห็นว่าข้อความในองค์ประกอบอัปเดตโดยอัตโนมัติหรือไม่ แอตทริบิวต์ที่สว่างจะสังเกตพร็อพเพอร์ตี้คลาสที่ตกแต่งด้วย @property
แล้วแสดงผลมุมมองอีกครั้งให้คุณ องค์ประกอบที่มีแสงสว่างจะช่วยรับหน้าที่นี้แทนคุณ
4. ตั้งค่าฉากด้วย Three.js
แสงพร้อม กล้องพร้อม เรนเดอร์!
องค์ประกอบที่กำหนดเองของเราจะใช้ third.js ในการแสดงผลโมเดลตัวต่อ 3 มิติของเรา เราต้องการทำบางสิ่งเพียงครั้งเดียวสำหรับแต่ละอินสแตนซ์ขององค์ประกอบ <brick-viewer>
เช่น ตั้งค่าฉาก 3.js, กล้อง และการจัดแสง เราจะเพิ่มข้อมูลเหล่านี้ลงในคลาส BrickViewer เราจะเก็บวัตถุบางอย่างไว้เป็นคุณสมบัติของคลาสเพื่อใช้ในภายหลัง ได้แก่ กล้อง ฉาก การควบคุม และโหมดแสดงภาพ
เพิ่มการตั้งค่าฉาก third.js ดังนี้
export class BrickViewer extends LitElement {
private _camera: THREE.PerspectiveCamera;
private _scene: THREE.Scene;
private _controls: OrbitControls;
private _renderer: THREE.WebGLRenderer;
constructor() {
super();
this._camera = new THREE.PerspectiveCamera(45, this.clientWidth/this.clientHeight, 1, 10000);
this._camera.position.set(150, 200, 250);
this._scene = new THREE.Scene();
this._scene.background = new THREE.Color(0xdeebed);
const ambientLight = new THREE.AmbientLight(0xdeebed, 0.4);
this._scene.add( ambientLight );
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(-1000, 1200, 1500);
this._scene.add(directionalLight);
this._renderer = new THREE.WebGLRenderer({antialias: true});
this._renderer.setPixelRatio(window.devicePixelRatio);
this._renderer.setSize(this.offsetWidth, this.offsetHeight);
this._controls = new OrbitControls(this._camera, this._renderer.domElement);
this._controls.addEventListener("change", () =>
requestAnimationFrame(this._animate)
);
this._animate();
const resizeObserver = new ResizeObserver(this._onResize);
resizeObserver.observe(this);
}
private _onResize = (entries: ResizeObserverEntry[]) => {
const { width, height } = entries[0].contentRect;
this._renderer.setSize(width, height);
this._camera.aspect = width / height;
this._camera.updateProjectionMatrix();
requestAnimationFrame(this._animate);
};
private _animate = () => {
this._renderer.render(this._scene, this._camera);
};
}
ออบเจ็กต์ WebGLRenderer
มีองค์ประกอบ DOM ที่แสดงโหมด 3.js ที่แสดงผล เข้าถึงได้ผ่านพร็อพเพอร์ตี้ domElement
เราสามารถแปลค่านี้ลงในลิเทอรัลของเทมเพลตการแสดงผลโดยใช้ไวยากรณ์ ${value}
นำข้อความ src
ที่เรามีในเทมเพลตออก แล้วแทรกองค์ประกอบ DOM ของโหมดแสดงภาพ
export class BrickViewer extends LitElement {
render() {
return html`
${this._renderer.domElement}
`;
}
}
เพื่อให้องค์ประกอบ DOM ของตัวแสดงผลแสดงได้อย่างครบถ้วน เราจำเป็นต้องตั้งค่าองค์ประกอบ <brick-viewer>
เองเป็น display: block
เราสามารถใส่รูปแบบในพร็อพเพอร์ตี้แบบคงที่ที่เรียกว่า styles
ซึ่งตั้งค่าเป็นลิเทอรัลของเทมเพลต css
เพิ่มการจัดรูปแบบนี้ในชั้นเรียน:
export class BrickViewer extends LitElement {
static styles = css`
/* The :host selector styles the brick-viewer itself! */
:host {
display: block;
}
`;
}
ตอนนี้ <brick-viewer>
กำลังแสดงโหมด 3.js ที่แสดงผล:
แต่... ว่างเปล่า เราจะลองระบุโมเดล
รถตักอิฐ
เราจะส่งพร็อพเพอร์ตี้ src
ที่เรากำหนดไว้ก่อนหน้านี้ไปยัง LDrawLoader ซึ่งจัดส่งด้วย 3.js
ไฟล์ LDraw สามารถแยกโมเดล Brick เป็นขั้นตอนสิ่งปลูกสร้างที่แยกจากกัน เข้าถึงจำนวนขั้นตอนทั้งหมดและการเปิดเผยตัวต่อแต่ละรายการได้ผ่าน LDrawLoader API
คัดลอกคุณสมบัติเหล่านี้ เมธอด _loadModel
ใหม่ และบรรทัดใหม่ในเครื่องมือสร้าง:
@customElement('brick-viewer')
export class BrickViewer extends LitElement {
private _loader = new LDrawLoader();
private _model: any;
private _numConstructionSteps?: number;
step?: number;
constructor() {
// ...
// Add this line right before this._animate();
(this._loader as any).separateObjects = true;
this._animate();
}
private _loadModel() {
if (this.src === null) {
return;
}
this._loader
.setPath('')
// Using our src property!
.load(this.src, (newModel) => {
if (this._model !== undefined) {
this._scene.remove(this._model);
this._model = undefined;
}
this._model = newModel;
// Convert from LDraw coordinates: rotate 180 degrees around OX
this._model.rotation.x = Math.PI;
this._scene.add(this._model);
this._numConstructionSteps = this._model.userData.numConstructionSteps;
this.step = this._numConstructionSteps!;
const bbox = new THREE.Box3().setFromObject(this._model);
this._controls.target.copy(bbox.getCenter(new THREE.Vector3()));
this._controls.update();
this._controls.saveState();
});
}
}
ควรโทรหา _loadModel
เมื่อใด โดยจะต้องเรียกใช้ทุกครั้งที่แอตทริบิวต์ src มีการเปลี่ยนแปลง ในการตกแต่งพร็อพเพอร์ตี้ src
ด้วย @property
เราได้เลือกใช้วงจรการอัปเดตองค์ประกอบที่มีแสงสว่าง เมื่อหนึ่งในสถานที่ตกแต่งเหล่านี้ การเปลี่ยนแปลงค่า เรียกชุดวิธีการว่าสามารถเข้าถึงค่าใหม่และค่าเก่าของพร็อพเพอร์ตี้ได้ วิธีการใช้วงจรที่เราสนใจชื่อว่า update
เมธอด update
จะใช้อาร์กิวเมนต์ PropertyValues
ซึ่งจะมีข้อมูลเกี่ยวกับพร็อพเพอร์ตี้ที่เพิ่งเปลี่ยนแปลง นี่คือที่ที่เหมาะที่สุดในการโทรหา _loadModel
เพิ่มเมธอด update
:
export class BrickViewer extends LitElement {
update(changedProperties: PropertyValues) {
if (changedProperties.has('src')) {
this._loadModel();
}
super.update(changedProperties);
}
}
ตอนนี้องค์ประกอบ <brick-viewer>
สามารถแสดงไฟล์ตัวต่อที่ระบุด้วยแอตทริบิวต์ src
ได้แล้ว
5. การแสดงโมเดลบางส่วน
ทีนี้เรามากำหนดค่าขั้นตอนการสร้างปัจจุบันกัน เราต้องการระบุ <brick-viewer step="5"></brick-viewer>
ได้ และเราควรจะมองว่าโมเดลอิฐมีลักษณะอย่างไรในขั้นตอนที่ 5 มาทำให้พร็อพเพอร์ตี้ step
เป็นพร็อพเพอร์ตี้ที่สังเกตได้ด้วยการตกแต่งด้วย @property
ตกแต่งพร็อพเพอร์ตี้ step
ดังนี้
export class BrickViewer extends LitElement {
@property({type: Number})
step?: number;
}
ต่อไปเราจะเพิ่มเมธอดตัวช่วยที่ทำให้เห็นเฉพาะตัวต่อจนถึงขั้นตอนการสร้างปัจจุบัน เราจะเรียกใช้ตัวช่วยในเมธอดการอัปเดตเพื่อให้ทำงานทุกครั้งที่พร็อพเพอร์ตี้ step
มีการเปลี่ยนแปลง
อัปเดตเมธอด update
และเพิ่มเมธอด _updateBricksVisibility
ใหม่
export class BrickViewer extends LitElement {
update(changedProperties: PropertyValues) {
if (changedProperties.has('src')) {
this._loadModel();
}
if (changedProperties.has('step')) {
this._updateBricksVisibility();
}
super.update(changedProperties);
}
private _updateBricksVisibility() {
this._model && this._model.traverse((c: any) => {
if (c.isGroup && this.step) {
c.visible = c.userData.constructionStep <= this.step;
}
});
requestAnimationFrame(this._animate);
}
}
โอเค เปิด devtools ของเบราว์เซอร์ และตรวจสอบองค์ประกอบ <brick-viewer>
เพิ่มแอตทริบิวต์ step
เข้าไปในลักษณะดังนี้
ดูว่าจะเกิดอะไรขึ้นกับโมเดลที่แสดงผล เราใช้แอตทริบิวต์ step
เพื่อควบคุมจำนวนโมเดลที่จะแสดงได้ ต่อไปนี้คือลักษณะที่ควรจะเป็นเมื่อตั้งค่าแอตทริบิวต์ step
เป็น "10"
6. การนำทางชุดอิฐ
ปุ่มไอคอน mwc
ผู้ใช้ปลายทางของ <brick-viewer>
ควรที่จะสามารถไปยังขั้นตอนบิลด์ผ่าน UI ได้ เรามาเพิ่มปุ่มสำหรับไปที่ขั้นตอนถัดไป ก่อนหน้า และขั้นตอนแรกกัน เราจะใช้องค์ประกอบเว็บของปุ่มของดีไซน์ Material เพื่อทำให้ง่าย เนื่องจากนำเข้า @material/mwc-icon-button
แล้ว เราพร้อมที่จะลดลงใน <mwc-icon-button></mwc-icon-button>
เราระบุไอคอนที่ต้องการใช้กับแอตทริบิวต์ไอคอนได้ เช่น <mwc-icon-button icon="thumb_up"></mwc-icon-button>
ดูไอคอนที่เป็นไปได้ทั้งหมดได้ที่ material.io/resources/icons
ลองเพิ่มปุ่มไอคอนบางปุ่มลงในวิธีการแสดงผลกัน
export class BrickViewer extends LitElement {
render() {
return html`
${this._renderer.domElement}
<div id="controls">
<mwc-icon-button icon="replay"></mwc-icon-button>
<mwc-icon-button icon="navigate_before"></mwc-icon-button>
<mwc-icon-button icon="navigate_next"></mwc-icon-button>
</div>
`;
}
}
การใช้ดีไซน์ Material ในหน้าเว็บของเรานั้นง่ายนิดเดียว ด้วยองค์ประกอบของเว็บ
การผูกกิจกรรม
ปุ่มเหล่านี้ควรทำหน้าที่บางอย่าง "ตอบกลับ" ควรรีเซ็ตขั้นตอนการสร้างเป็น 1 "navigate_before" ควรลดขั้นตอนการสร้าง และปุ่ม "navigate_next" ควรเพิ่มตัวเลข lit-Element ทำให้เพิ่มฟังก์ชันนี้ได้ง่ายๆ ด้วยการเชื่อมโยงเหตุการณ์ ในลิเทอรัลเทมเพลต HTML ให้ใช้ไวยากรณ์ @eventname=${eventHandler}
เป็นแอตทริบิวต์ขององค์ประกอบ ตอนนี้ eventHandler
จะทำงานเมื่อตรวจพบเหตุการณ์ eventname
ในองค์ประกอบนั้น ลองดูตัวอย่างจากการเพิ่มเครื่องจัดการกิจกรรมการคลิกลงในปุ่มไอคอน 3 ปุ่มดังนี้
export class BrickViewer extends LitElement {
private _restart() {
this.step! = 1;
}
private _stepBack() {
this.step! -= 1;
}
private _stepForward() {
this.step! += 1;
}
render() {
return html`
${this._renderer.domElement}
<div id="controls">
<mwc-icon-button @click=${this._restart} icon="replay"></mwc-icon-button>
<mwc-icon-button @click=${this._stepBack} icon="navigate_before"></mwc-icon-button>
<mwc-icon-button @click=${this._stepForward} icon="navigate_next"></mwc-icon-button>
</div>
`;
}
}
ลองคลิกปุ่มต่างๆ ได้ทันที เยี่ยมมาก
รูปแบบ
ปุ่มใช้งานได้ แต่ประสิทธิภาพไม่ดี ทุกคนอยู่รวมกันที่ด้านล่าง มาจัดรูปแบบให้ซ้อนทับกันบนฉากกัน
หากต้องการใช้รูปแบบกับปุ่มเหล่านี้ เราจะกลับไปที่พร็อพเพอร์ตี้ static styles
รูปแบบเหล่านี้มีการกำหนดขอบเขต ซึ่งหมายความว่าจะใช้กับองค์ประกอบภายในคอมโพเนนต์เว็บนี้เท่านั้น หนึ่งในความสนุกของการเขียนคอมโพเนนต์เว็บก็คือ ตัวเลือกอาจง่ายกว่า และ CSS ก็จะอ่านและเขียนได้ง่ายขึ้น สวัสดี BEM
อัปเดตรูปแบบให้มีลักษณะเช่นนี้
export class BrickViewer extends LitElement {
static styles = css`
:host {
display: block;
position: relative;
}
#controls {
position: absolute;
bottom: 0;
width: 100%;
display: flex;
}
`;
}
รีเซ็ตปุ่มกล้อง
ผู้ใช้ปลายทางของ <brick-viewer>
สามารถหมุนฉากโดยใช้ตัวควบคุมด้วยเมาส์ได้ ระหว่างที่เราเพิ่มปุ่ม ให้เพิ่มปุ่มสำหรับรีเซ็ตกล้องไปยังตำแหน่งเริ่มต้น <mwc-icon-button>
อื่นที่มีการเชื่อมโยงกิจกรรมการคลิกจะทำให้งานสำเร็จ
export class BrickViewer extends LitElement {
private _resetCamera() {
this._controls.reset();
}
render() {
return html`
<div id="controls">
<!-- ... -->
<!-- Add this button: -->
<mwc-icon-button @click=${this._resetCamera} icon="center_focus_strong"></mwc-icon-button>
</div>
`;
}
}
การนำทางที่รวดเร็วขึ้น
อิฐบางชุดมีหลายขั้นตอน ผู้ใช้อาจต้องการข้ามไปยังขั้นตอนที่เฉพาะเจาะจง การเพิ่มแถบเลื่อนพร้อมหมายเลขขั้นตอนจะช่วยให้ไปยังส่วนต่างๆ ได้อย่างรวดเร็ว เราจะใช้องค์ประกอบ <mwc-slider>
สำหรับขั้นตอนนี้
แถบเลื่อน mwc
องค์ประกอบแถบเลื่อนต้องมีข้อมูลสำคัญ 2-3 อย่าง เช่น ค่าแถบเลื่อนต่ำสุดและสูงสุด ค่าแถบเลื่อนต่ำสุดจะเป็น "1" ได้เสมอ ค่าแถบเลื่อนสูงสุดควรเป็น this._numConstructionSteps
ถ้าโหลดโมเดลแล้ว เราบอกค่าเหล่านี้ได้ <mwc-slider>
ผ่านแอตทริบิวต์ นอกจากนี้เรายังใช้คำสั่ง ifDefined
lit-html เพื่อหลีกเลี่ยงการตั้งค่าแอตทริบิวต์ max
ได้ หากไม่ได้กำหนดพร็อพเพอร์ตี้ _numConstructionSteps
ไว้
เพิ่ม <mwc-slider>
ระหว่าง "ด้านหลัง" และ "ไปข้างหน้า" ปุ่ม:
export class BrickViewer extends LitElement {
render() {
return html`
<div id="controls">
<!-- ... backwards button -->
<!-- Add this slider: -->
<mwc-slider
step="1"
pin
markers
min="1"
max=${ifDefined(this._numConstructionSteps)}
></mwc-slider>
<!-- ... forwards button -->
</div>
`;
}
}
ข้อมูล "ขึ้น"
เมื่อผู้ใช้เลื่อนแถบเลื่อน ขั้นตอนการสร้างปัจจุบันควรเปลี่ยนไป และการแสดงผลของโมเดลควรได้รับการอัปเดตตามนั้น องค์ประกอบแถบเลื่อนจะแสดงเหตุการณ์การป้อนข้อมูลเมื่อใดก็ตามที่มีการลากแถบเลื่อน เพิ่มการเชื่อมโยงเหตุการณ์บนตัวแถบเลื่อนเพื่อติดตามเหตุการณ์นี้และเปลี่ยนขั้นตอนการสร้าง
เพิ่มการเชื่อมโยงกิจกรรม
export class BrickViewer extends LitElement {
render() {
return html`
<div id="controls">
<!-- ... -->
<!-- Add the @input event binding: -->
<mwc-slider
...
@input=${(e: CustomEvent) => this.step = e.detail.value}
></mwc-slider>
<!-- ... -->
</div>
`;
}
}
เย่! เราสามารถใช้แถบเลื่อนเพื่อเปลี่ยนระดับที่จะแสดงได้
ข้อมูล "ล่ม"
ยังมีอีกอย่าง เมื่อ "กลับ" และ "ถัดไป" ปุ่มใช้เพื่อเปลี่ยนขั้นตอน ต้องอัปเดตแฮนเดิลแถบเลื่อน เชื่อมโยงแอตทริบิวต์ค่าของ <mwc-slider>
กับ this.step
เพิ่มการเชื่อมโยง value
:
export class BrickViewer extends LitElement {
render() {
return html`
<div id="controls">
<!-- ... -->
<!-- Add the value property binding: -->
<mwc-slider
...
value=${ifDefined(this.step)}
></mwc-slider>
<!-- ... -->
</div>
`;
}
}
เราใช้แถบเลื่อนเกือบเสร็จแล้ว เพิ่มรูปแบบ Flex เพื่อให้เล่นกับการควบคุมอื่นๆ อย่างสวยงาม
export class BrickViewer extends LitElement {
static styles = css`
/* ... */
mwc-slider {
flex-grow: 1;
}
`;
}
และจะต้องเรียก layout
ในองค์ประกอบแถบเลื่อนด้วย โดยเราจะทำในเมธอดอายุการใช้งาน firstUpdated
ซึ่งเรียกว่าเมื่อมีการจัดวาง DOM ครั้งแรก เครื่องมือตกแต่ง query
จะช่วยให้เรารับการอ้างอิงองค์ประกอบแถบเลื่อนในเทมเพลตได้
export class BrickViewer extends LitElement {
@query('mwc-slider')
slider!: Slider|null;
async firstUpdated() {
if (this.slider) {
await this.slider.updateComplete
this.slider.layout();
}
}
}
รายการต่อไปนี้คือการเพิ่มแถบเลื่อนทั้งหมดไว้ด้วยกัน (พร้อมแอตทริบิวต์ pin
และ markers
เพิ่มเติมบนแถบเลื่อนเพื่อทำให้ดูเท่)
export class BrickViewer extends LitElement {
@query('mwc-slider')
slider!: Slider|null;
static styles = css`
/* ... */
mwc-slider {
flex-grow: 1;
}
`;
async firstUpdated() {
if (this.slider) {
await this.slider.updateComplete
this.slider.layout();
}
}
render() {
return html`
${this._renderer.domElement}
<div id="controls">
<mwc-icon-button @click=${this._restart} icon="replay"></mwc-icon-button>
<mwc-icon-button @click=${this._stepBack} icon="navigate_before"></mwc-icon-button>
<mwc-slider
step="1"
pin
markers
min="1"
max=${ifDefined(this._numConstructionSteps)}
?disabled=${this._numConstructionSteps === undefined}
value=${ifDefined(this.step)}
@input=${(e: CustomEvent) => this.constructionStep = e.detail.value}
></mwc-slider>
<mwc-icon-button @click=${this._stepForward} icon="navigate_next"></mwc-icon-button>
<mwc-icon-button @click=${this._resetCamera} icon="center_focus_strong"></mwc-icon-button>
</div>
`;
}
}
สินค้าสุดท้ายมาแล้ว
7. บทสรุป
เราได้เรียนรู้มากมายเกี่ยวกับวิธีใช้องค์ประกอบที่สว่างเพื่อสร้างองค์ประกอบ HTML ของเราเอง เราได้เรียนรู้วิธีต่อไปนี้
- กำหนดองค์ประกอบที่กำหนดเอง
- ประกาศ API แอตทริบิวต์
- แสดงผลมุมมองสำหรับองค์ประกอบที่กำหนดเอง
- ห่อหุ้มรูปแบบ
- ใช้เหตุการณ์และพร็อพเพอร์ตี้เพื่อส่งข้อมูล
ดูข้อมูลเพิ่มเติมเกี่ยวกับองค์ประกอบที่มีแสงได้ที่เว็บไซต์อย่างเป็นทางการ
คุณสามารถดูองค์ประกอบของผู้ดูอิฐที่เสร็จสมบูรณ์ได้ที่ stackblitz.com/edit/brick-viewer-complete
เรามีการจัดส่งเครื่องมือตรวจสอบอิฐใน NPM ด้วย และคุณสามารถดูแหล่งที่มาได้ที่ที่เก็บของ GitHub