1. บทนำ
คอมโพเนนต์ของเว็บ
Web Components คือชุดมาตรฐานเว็บที่ช่วยให้นักพัฒนาซอฟต์แวร์ขยาย HTML ด้วยองค์ประกอบที่กำหนดเองได้ ใน Codelab นี้ คุณจะได้กำหนดองค์ประกอบ <brick-viewer> ซึ่งจะแสดงโมเดลอิฐได้
lit-element
เราจะใช้ lit-element เพื่อช่วยกำหนดองค์ประกอบที่กำหนดเอง <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 เราจึงใช้ประโยชน์จาก Declarative API และกำหนดแอตทริบิวต์แหล่งที่มาได้เหมือนกับแท็ก <img> หรือ <video> lit-element ช่วยให้การตกแต่งพร็อพเพอร์ตี้ของคลาสด้วย @property เป็นเรื่องง่าย ตัวเลือก type ช่วยให้คุณระบุวิธีที่ LitElement แยกวิเคราะห์พร็อพเพอร์ตี้เพื่อใช้เป็นแอตทริบิวต์ HTML ได้
กําหนดพร็อพเพอร์ตี้และแอตทริบิวต์ src ดังนี้
export class BrickViewer extends LitElement {
@property({type: String})
src: string|null = null;
}
<brick-viewer> มีแอตทริบิวต์ src ที่เราตั้งค่าใน HTML ได้แล้ว ค่าของพร็อพเพอร์ตี้นี้สามารถอ่านได้จากภายในคลาส BrickViewer ของเราอยู่แล้วด้วย lit-element
การแสดงค่า
เราสามารถแสดงค่าของแอตทริบิวต์ src ได้โดยใช้ค่าดังกล่าวในเทมเพลตสตริงของเมธอดการแสดงผล ประมาณค่าในช่วงลงในเทมเพลตสตริงโดยใช้ไวยากรณ์ ${value}
export class BrickViewer extends LitElement {
render() {
return html`<div>Brick model: ${this.src}</div>`;
}
}
ตอนนี้เราเห็นค่าของแอตทริบิวต์ src ในองค์ประกอบ <brick-viewer> ในหน้าต่าง ลองเปิดเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์ของเบราว์เซอร์ แล้วเปลี่ยนแอตทริบิวต์ src ด้วยตนเอง ลองเลย...
...คุณสังเกตไหมว่าข้อความในองค์ประกอบอัปเดตโดยอัตโนมัติ lit-element จะสังเกตพร็อพเพอร์ตี้ของคลาสที่ตกแต่งด้วย @property และแสดงผลมุมมองอีกครั้งให้คุณ lit-element จะจัดการงานหนักๆ ให้คุณเอง
4. ตั้งค่าฉากด้วย Three.js
ไฟพร้อม กล้องพร้อม แสดงผลได้เลย
Custom Element ของเราจะใช้ three.js เพื่อแสดงโมเดลอิฐ 3 มิติ มีบางอย่างที่เราต้องการทำเพียงครั้งเดียวสำหรับแต่ละอินสแตนซ์ขององค์ประกอบ <brick-viewer> เช่น การตั้งค่าฉาก กล้อง และแสงสว่างของ three.js เราจะเพิ่มสิ่งเหล่านี้ลงในตัวสร้างของคลาส BrickViewer เราจะเก็บออบเจ็กต์บางอย่างไว้เป็นพร็อพเพอร์ตี้ของคลาสเพื่อให้ใช้ได้ในภายหลัง ได้แก่ กล้อง ฉาก ตัวควบคุม และโปรแกรมแสดงผล
เพิ่มการตั้งค่าฉาก three.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 ที่แสดงฉาก three.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> กำลังแสดงฉาก three.js ที่เรนเดอร์แล้ว

แต่...มันว่างเปล่า มาใส่โมเดลกัน
ตัวโหลดอิฐ
เราจะส่งพร็อพเพอร์ตี้ src ที่เรากำหนดไว้ก่อนหน้านี้ไปยัง LDrawLoader ซึ่งมาพร้อมกับ three.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 ทำให้เราเลือกใช้พร็อพเพอร์ตี้ในวงจรการอัปเดตของ Lit-Element เมื่อใดก็ตามที่ค่าของพร็อพเพอร์ตี้ที่ตกแต่งเหล่านี้เปลี่ยนแปลง ระบบจะเรียกใช้ชุดเมธอดที่เข้าถึงค่าใหม่และค่าเก่าของพร็อพเพอร์ตี้ได้ เมธอดวงจรที่เราสนใจเรียกว่า 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-icon-button
ผู้ใช้ปลายทางของ <brick-viewer> ควรไปยังขั้นตอนการสร้างผ่าน UI ได้ด้วย มาเพิ่มปุ่มสำหรับไปที่ขั้นตอนถัดไป ขั้นตอนก่อนหน้า และขั้นตอนแรกกัน เราจะใช้คอมโพเนนต์เว็บปุ่มของ Material Design เพื่อให้ใช้งานได้ง่าย เนื่องจากเราได้นำเข้า @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 Design ในหน้าเว็บของเรานั้นง่ายมากด้วยคอมโพเนนต์ของเว็บ
การเชื่อมโยงเหตุการณ์
ปุ่มเหล่านี้ควรทำงานได้จริง ปุ่ม "ตอบ" จะรีเซ็ตขั้นตอนการสร้างเป็น 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-slider
องค์ประกอบแถบเลื่อนต้องมีข้อมูลสำคัญบางอย่าง เช่น ค่าต่ำสุดและสูงสุดของแถบเลื่อน ค่าต่ำสุดของแถบเลื่อนจะเป็น "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 Decorator จะช่วยให้เราอ้างอิงองค์ประกอบแถบเลื่อนในเทมเพลตได้
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. บทสรุป
เราได้เรียนรู้มากมายเกี่ยวกับวิธีใช้ lit-element เพื่อสร้างองค์ประกอบ HTML ของเราเอง เราได้เรียนรู้วิธีการต่อไปนี้
- กำหนดองค์ประกอบที่กำหนดเอง
- ประกาศ API แอตทริบิวต์
- แสดงผลมุมมองสำหรับองค์ประกอบที่กำหนดเอง
- แคปซูลสไตล์
- ใช้เหตุการณ์และพร็อพเพอร์ตี้เพื่อส่งข้อมูล
หากต้องการดูข้อมูลเพิ่มเติมเกี่ยวกับ LitElement โปรดอ่านข้อมูลเพิ่มเติมที่เว็บไซต์อย่างเป็นทางการ
คุณดูองค์ประกอบ Brick-Viewer ที่เสร็จสมบูรณ์ได้ที่ stackblitz.com/edit/brick-viewer-complete
นอกจากนี้ brick-viewer ยังจัดส่งใน NPM และคุณดูแหล่งที่มาได้ที่ที่เก็บ Github