การเขียน CSS สำหรับเว็บที่เขียนด้วย HTML5 (CSS Standards v.2)

สำหรับ Basic CSS Standards ที่เคยเขียนไปใน CSS Coding Standards (ภาษาไทย) เป็นแบบขั้นพื้นฐานจริงๆที่กล่าวถึงในเรื่องการเขียน CSS ยังไงให้อ่านง่าย (Readability), สื่อความหมาย (Semantics) ซึ่งมีผลกับเรื่องการทำ SEO ด้วย, รวมถึงในเรื่องของการนำกลับมาใช้ใหม่ (Reusability) ส่วนสำหรับโพสต์นี้เราจะมาเข้าเรื่องพื้นฐานอีกเหมือนกัน แต่รวมถึงการใช้ CSS สำหรับ HTML5 ด้วย ซึ่งอาจมีความเข้าใจที่ไม่ค่อยถูกต้องนักอยู่จากที่เคยได้ยินมาจากเพื่อนๆมา และจากการอ่าน Writing the best CSS when building with HTML5 ที่เขียนโดย Todd Motto เลยคิดว่าเราควรจะมาเขียนสรุปให้ลึกลงไปมากกว่าเรื่อง Standard อีกหน่อย

เริ่มกันที่ HTML แบบธรรมดาเดิมๆก่อน
หลักการใช้ HTML กับ CSS หลักๆคือการทำให้มันไม่มีเงื่อนไขมากนักครับ อย่างเช่นเรื่อง Nested การทำให้มันไม่ไปติดเงื่อนไขกับการใช้ HTML เดี๋ยวเรามาลองดูตัวอย่างของการเขียนโครงสร้าง HTML ที่พอจะมีโอกาสเขียน CSS เป็นแบบ Nested กันได้มากๆเลยคือ Ordered list และ Unordered list

<ul>
    <li>
        <a href="#">Link</a>
    </li>
    <li>
        <a href="#">Link</a>
    </li>
</ul>

แล้วเวลาเราจะเขียน CSS เราจะทำยังไงครับ? มันมีโอกาสที่จะมีการเขียนเป็นแบบใช้ HTML element เป็น selector ได้ อย่างเช่น

ul {}
ul li {}
ul li a {}

การเขียนแบบนี้ จะทำให้เรายึดรูปแบบตาม HTML แบบนี้ไปโดยสิ้นเชิงและที่สำคัญคือสไตล์นี้มันจะเหมือนกันหมดทั้ง Document และเปลี่ยนรูปแบบไปจากนี้ไม่ได้

ซึ่งที่ควรทำคือการใช้ Class แทนครับ

<ul class="nav">
    <li class="nav-item">
        <a href="#">Link</a>
    </li>
    <li class="nav-item">
        <a href="#">Link</a>
    </li>
</ul>

พอเป็นรูปแบบนี้ เราก็จะสามารถเขียน CSS แบบที่สามารถ Reuse ได้แล้ว

.nav {}
.nav-item {}
.nav-item a {}

ลองนึกภาพดูนะครับ ถ้าเขียน CSS selector ที่ชี้ไปที่ Class แล้ว ถ้าเราอยากใส่ Style แบบ Class นั้นๆที่ไหนเราก็สามารถเขียนชื่อ Class นั้นลงไปใน HTML element ที่ต้องการได้เลย ตอนนี้มันมี Reuseability มากขึ้น และหลีกเลี่ยงรูปแบบ Nested มาได้ในระดับดีแล้วครับ

HTML5
มาถึงเรื่อง HTML5 และ Elements ใหม่ๆที่มีมาให้ใช้ ซึ่งอาจเกิดความเข้าใจผิดในการใช้งานมันได้ เท่าที่ผมเคยได้ยินมาคือมีบาง Blog เขียนไปว่า “เราไม่ต้องมาประกาศ Div เยอะๆเหมือนเดิมแล้วและเวลาเขียน CSS ก็ไม่ต้องเขียน Class หรือ ID ไปใส่ใน Div จำนวนมากแล้ว ชี้ไปที่ Header, Section, Footer, … ได้เลย” ซึ่งมันไม่ใช่วิธีที่ดีเท่าไหร่นักน่ะครับ จะว่าไม่ควรเลยก็ได้ครับ เพราะมันก็ไปชี้ที่ Elements อยู่ดี ยกตัวอย่างเช่น

<header>
    <!-- Content -->
</header>

และลองมาดูถึงหลักการใช้งานของ HTML5 เมื่อศึกษาจาก HTML5 Reference และ HTML5 Structural Elements อย่างเป็นทางการของ World Wide Web Consortium (W3C) แล้ว จะทราบว่า Header, Section, Article, Nav, Footer elements ทั้งหลายเหล่านี้ สามารถใช้ซ้ำใน document เดียวกันได้ เพราะฉะนั้นแล้ว การเขียน CSS ที่ชี้ไปยังตัว HTML element เลยนั้น เป็นสิ่งที่ไม่ควรจะทำครับ เพื่อรักษาคุณสมบัติในเรื่อง reusability ของ CSS ไว้ อย่างการเขียน CSS แบบนี้ ไม่ควรทำครับ

header {}
section {}
footer {}

ควรหลีกเลี่ยงการใช้ HTML element เป็น CSS selector ครับ เรียกได้ว่าเป็นสิ่งที่ควรระลึกถึงตอนเขียน CSS เป็นหลักเลย
ควรใช้ class มาแทนเหมือนตัวอย่างก่อนหน้านี้ครับ เพราะ header นั้นสามารถอยู่ใน article ก็ได้ อยู่ใน section ก็ได้ หรือรวมถึงอยู่นอกสุด เป็น header ของหน้าเว็บนั้นก็ได้ สิ่งที่เขียนใน CSS ก็จะแตกต่างกันออกไปครับ ควรใช้ class แทนจะดีกว่าครับ

หลีกเลี่ยงการสร้าง Selector แบบมีเงื่อนไข
อย่างเช่น

ul.nav
div#logo
footer.footer-container

สิ่งเหล่านี้มันจะลด scalability ของเราไปครับ รวมถึงมีผลทำให้ performance ต่ำลงไปด้วยเนื่องจากทำให้เบราว์เซอร์ต้องตรวจสอบเงื่อนไขก่อนจากที่ตรวจสอบเพียง class เฉยๆ

และจากตัวอย่างข้างบน จะเห็นว่ามีการใช้ ID ชื่อ logo หรือ #logo ใน CSS นั้น กล่าวคือ มันไม่ได้ผิดอะไรที่จะเขียน CSS โดยใช้ selector เป็น ID ครับ แต่เราจะใช้มันอีกไม่ได้เลยในหน้าเดียวกัน เพราะ document หนึ่งๆจะสามารถมี ID ที่ชื่อนั้นๆได้เพียง 1 ที่เท่านั้น ความเห็นส่วนตัวผมเลยคือไม่แนะนำครับ ถึงมันจะเฉพาะเจาะจงอย่างไรก็ตาม สไตล์การเขียนของผมคือใน CSS จะใช้ class เท่านั้น และใช้ ID เท่าที่จำเป็น ส่วนใหญ่แล้วจะใช้ ID กับ JavaScript ครับ แต่ก็แล้วแต่ผู้เขียนจะเห็นสมควรครับว่าจะใช้มันอย่างไร

สรุป
เมื่อรวมเรื่อง CSS Coding Standards (ภาษาไทย) กับโพสต์นี้เข้าไปจะสังเกตได้ว่าเรื่องที่เน้นคือ

1. Readability:
เรื่องนี้ควรจะทำกับทุก programming language ครับ เคยมีอาจารย์ท่านหนึ่งบอกกับผมว่า เวลาเราเขียนโปรแกรมคนเดียว จะมีเพียง 2 คนที่รู้โค้ดเราว่ามันทำงานยังไง แต่พอนานๆวันเข้าจะเหลือเพียงคนเดียว คือ พระเจ้า ฮ่าๆๆ คือเราเองก็อาจจะลืมโค้ดที่เราเขียนไปได้ครับ ทำอย่างไรให้อ่านง่ายที่สุด มีการ comment ไว้ว่า บรรทัดนี้, function นี้, ตัวแปรนี้ หรืออื่นๆที่จำเป็นนั้น มันทำงานอย่างไร
และในเรื่องการเขียนให้มันเป็น Multiple-line สำหรับ CSS ในโพสต์ v.1 บางท่านอาจจะกังวลว่า comment ยาวๆ เขียนโค้ดเคาะบรรทัดไป มันจะทำให้ไฟล์ใหญ่ขึ้น โหลดได้ช้าลง เรื่องพวกนี้จะหมดกังวลไป เนื่องจากเราสามารถ compile และ minify มันได้ครับ สำหรับ CSS สามารถใช้ CSS Pre-processor อย่าง LESS หรือ SASS ในการทำงานนี้ได้ ซึ่งจะกล่าวถึงถัดไปอีกในโพสต์ต่อไปครับ ถ้ายังไม่ทราบว่ามันคืออะไรและอยากรู้เลย ผมแนะนำให้ศึกษา SASS ได้เลยครับ มันมีตัวช่วยให้เราเขียน CSS ได้สะดวกขึ้นมาก แต่เรื่อง Standard ของมันเราควรจะเข้าใจก่อนนะครับ เหมือนเขียน JavaScript แล้วจะไปเขียน Coffee Script ถ้ายังไม่เข้าใจ JavaScript เพียงพอ ผมก็จะยังไม่แนะนำให้ไปเขียน Coffee Script เลย

2. Semantics:
เหมือนกับ Readability ครับ ทำให้มันสื่อความหมาย class นี่คืออะไร, ตัวแปรนี้ชื่ออะไร ทำอะไร ไม่ต้องใช้อะไรประหลาดมากจนตัวเองไม่เข้าใจว่ามันคืออะไรครับ

3. Reusability:
เรื่องนี้ถือเป็นจุดเด่นเลยที่ถ้าทำได้ ออกแบบดีดีแล้ว มันจะทำให้ performance ดีมาก ไฟล์เบาลง และมี Scalability ที่ดีครับ

4. Nested:
หลีกเลี่ยงการเขียน CSS selector ที่เป็น nested ลากต่อกันยาวๆ และหลีกเลี่ยงการใช้เงื่อนไขและรูปแบบที่ strict กับ CSS ครับ มันจะทำให้ใช้งานยากขึ้น

5. ท่าไม้ตายที่ไว้หักล้างทุกสิ่ง !important Rule ฮ่าๆๆๆ (เสียงตัวโกง):
!important; ท่านี้ถ้าเคยเขียน CSS คงเข้าใจครับ มันมีระดับ priority สูงที่สุดของ CSS แล้ว ระดับ priority ไล่ตามลำดับตามนี้
!important > Inline CSS > Internal CSS > External CSS และ
ID selector > Class selector > Attribute selector
และลำดับความสำคัญจะมากขึ้นตามความซ้อนกันของ Selector ยกตัวอย่างเช่น

.header {
    font-size: 18px;
}
.header p {
    font-size: 20px;
}

ในรูปแบบนี้ขนาดฟอนต์ที่อยู่ใน header Class จะมีขนาด 18px แต่ถ้าอยู่ใน p ที่อยู่ใน header Class ขนาดฟอนต์ของ p นั้นจะมีขนาด 20px ครับ อะไรประมาณนี้ ว่าง่ายๆคือถ้ามันยิ่งชี้เฉพาะมากขึ้น ค่า priority ตัวนั้นๆก็จะสูงมากขึ้น และมันก็จะซับซ้อนมากขึ้น ถึงได้กล่าวไปว่าควรหลีกเลี่ยงรูปแบบ Nested และเงื่อนไข เพราะงานมันจะยากขึ้นและ maintenance ได้ยากขึ้นด้วย

แต่ส่วน !important Rule นี่เขาป๋าสุด ถ้าเจอเข้าไปนี่ Value ใน Property ของ Selector นั้นๆจะเป็นค่าของตาม !important นั้นทันที สรุปหลีกเลี่ยงการใช้มันให้มากที่สุดครับ ไม่งั้นอาจเกิดปัญหาภายหลังได้ ยิ่งถ้างานใหญ่ๆและนักพัฒนาหลายคนแล้วอาจปวดหัวได้ครับ อันนี้ประสบการณ์ตรงเลย สำหรับการใช้งาน !important คือ
1. เอาไว้แก้งานด่วน
2. การทดสอบอะไรบางอย่าง ยกตัวอย่างเช่น JavaScript หลายๆตัวชอบไปใส่ Style แบบ Inline Style ใน HTML elements เลย ที่เห็นบ่อยๆจะเป็นพวกทำ Slide เนี่ย เราอาจจะใช้ !important มาช่วยตอนทดลองได้ครับ
แค่จำไว้ว่ามัน Overide ทุกอย่าง จงใช้อย่างระมัดระวังและเก็บให้พ้นมือเด็กครับ ;p

How to embed video to PrestaShop’s Product detail page, without additional module (Coding part)

In PrestaShop, you could simply embed video from other website like Youtube using iframe tag as we know from this article.

Video from Youtube on PrestaShop's Product detail page.
Video from Youtube on PrestaShop’s Product detail page.

Or even media file from this article.

But for media/video file that have to upload, we have to modify the code before, to set file size and extension.
So here! I’ll let you know how to figure out and do it! : )

There is just only 1 file that you need to edit.
Take it easy : )

Open config.base.php
(path is, /yourproject/admin/ajaxfilemanager/inc/config.base.php)

Then go to line 74, you will see this code,

//UPLOAD OPTIONS CONFIG
define('CONFIG_UPLOAD_MAXSIZE', 5000 * 1024 ); //by bytes
//define('CONFIG_UPLOAD_MAXSIZE', 2048); //by bytes
//define('CONFIG_UPLOAD_VALID_EXTS', 'txt');//

So you just simply change it to the size what you want, for example,

define('CONFIG_UPLOAD_MAXSIZE', 20000 * 1024 ); //by bytes

And we go to line 80

define('CONFIG_OVERWRITTEN', false); //overwirte when processing paste
define('CONFIG_UPLOAD_VALID_EXTS', 'gif,jpg,png');// // 
//define('CONFIG_UPLOAD_VALID_EXTS', 'gif,jpg,png,bmp,tif,zip,sit,rar,gz,tar,htm,html,mov,mpg,avi,asf,mpeg,wmv,aif,aiff,wav,mp3,swf,ppt,rtf,doc,pdf,xls,txt,xml,xsl,dtd');//
define("CONFIG_VIEWABLE_VALID_EXTS", 'gif,jpg,png');
//define('CONFIG_UPLOAD_VALID_EXTS', 'gif,jpg,png,txt'); // 
define('CONFIG_UPLOAD_INVALID_EXTS', '');

And you just comment line 81 out and uncomment line 82, and add file extension what you want, such as mp4 and ogv for HTML5 video.
like this,

// define('CONFIG_UPLOAD_VALID_EXTS', 'gif,jpg,png');// // 
define('CONFIG_UPLOAD_VALID_EXTS', 'gif,jpg,png,bmp,tif,zip,sit,rar,gz,tar,htm,html,mov,mpg,avi,asf,mpeg,wmv,aif,aiff,wav,mp3,swf,ppt,rtf,doc,pdf,xls,txt,xml,xsl,dtd,mp4,ogv');

Then save the file!

It’s all set!

Now you can embed video into product detail page and make your e-commerce site more lively! ;D

Video from Youtube and uploaded video in Product detail page.
Video from Youtube and uploaded video in Product detail page.

nth-child ใช้ยังไง

:nth-child นี้จะสามารถใช้ใน element อะไรที่นับได้ เช่น unordered lists (ul) หรือ ordered lists (ol) โดยใช้เป็น selector ที่ชี้ไปยัง (list) li (หมายเหตุ: จะใช้กับ element อื่นๆก็ได้นะครับ แต่ส่วนตัวผมไม่ค่อยได้ใช้เท่าไหร่)
ตัวอย่างเช่น

ul li:nth-child(3n+3) {
    color: #00ff00;
}

ซึ่งโค้ดนี้จะ select ตัวที่อยู่ใน unordered lists ตัวที่ 3, 6, 9, 12 ให้มีตัวอักษรเป็นสีเขียว
ว่าแต่โค้ดนั้นมีการทำงานอย่างไร?

Continue reading

How to upload video into product detail page on PrestaShop (Without additional module)

Video file(s) type that you have to prepare is,
1. .mp4 (For Internet Explorer 9+, Chrome 6+, Safari 5+, and Safari Mobile as well)
2. .ogv (For Chrome 6+, Firefox 3.6+, Opera 10.6+)

Then follow these steps,

Continue reading

CSS Coding Standards (ภาษาไทย)

เราเขียนโค้ดตามรูปแบบตามมาตรฐานไปทำไม?
การเขียนให้เป็นไปตามมาตรฐานนี้มันจะช่วยให้โค้ดของเรานั้นสามารถจัดการได้ง่ายขึ้น ดูเป็นระบบระเบียบมากขึ้น ทำงานร่วมกับคนอื่นเป็นทีมได้ง่ายขึ้น ลดปัญหาที่อาจจะเกิดขึ้นได้จากการอ่านโค้ด เช่น ทำให้ประสิทธิภาพการทำงานแย่ลง เนื่องจากมี cost ด้านเวลาที่สูงขึ้นจากการอ่านโค้ดที่ต้องมา maintenance รวมถึงเรื่อง performance สำหรับเว็บด้วยเช่นกัน เช่น หาก CSS ถูกเขียนขึ้นในรูปแบบ nested เยอะๆ ก็มีผลทำให้เว็บอ่านและ render ช้าลง แต่หากโค้ดที่เราเขียนขึ้นมานั้นหากเขียนถูกต้องตามมาตรฐานแล้วมันจะทำให้อ่านได้ง่ายขึ้น และนั่นก็จะช่วยให้ debugging ได้ง่ายขึ้นอีกด้วย

คำว่ามาตรฐานสำหรับ CSS ในที่นี้ผมจะหมายถึงในเชิง Readable และ Semantics เป็นหลักนะครับ
ส่วนเรื่อง Reusability นี่เป็นสิ่งที่ CSS ควรจะทำได้อยู่แล้ว

Block Style

selector {
    property: value;
}
  • แต่ละ selector ควรแบ่งเป็นบรรทัดของตัวเอง ถ้าต้องการประกาศหลายๆ selector ต่อกัน ควรใช้เครื่องหมาย comma (,) ปิด selector แล้วตัวต่อมาก็ขึ้นบรรทัดใหม่
  • Property-value ก็ควรแบ่งเป็นบรรทัดเหมือนกัน และควรใช้ indent มา 1 tab และปิดด้วยเครื่องหมาย semicolon (;)
  • การใช้เครื่องหมายปีกกาปิด (}) ควรไว้ชิดซ้ายสุด ตรงกับตำแหน่งที่เราเปิด selector เอาไว้
  • แต่ส่วนแต่ละส่วนโดยการเว้นบรรทัดว่างไว้ 2 บรรทัด แต่ภายใน block เดียวกัน ไม่ควรเว้นว่างไว้

แบบที่ควรทำ:

#selector-1,
#selector-2,
#selector-3 {
    background: #fff;
    color: #000;
}

แบบที่ไม่ควรทำ:

#selector-1, #selector-2, #selector-3 {
    background: #fff; color: #000;
    }

แบบนี้ก็ไม่ควรทำ:

#selector-1 { background: #fff; color: #000; }

Selectors

  • การตั้งชื่อตัว selector ควรใช้ตัวอักษรตัวพิมพ์เล็ก (lowercase) และใช้เครื่องหมายยัตภังค์ (hyphen หรือเครื่องหมาย -) แทนการใช้ตัวพิมพ์ใหญ่มาเชื่อมต่อคำหรือใช้ตัวขีดเส้นใต้ (underscore หรือ _)
  • ใช้ภาษาที่มนุษย์อ่านออก ตั้งชื่อให้สื่อความหมายว่า selector ตัวนี้คืออะไร

แบบที่ควรทำ:

#comment-form {
    margin: 0;
}

แบบที่ไม่ควรทำ:

#commentForm { /* Avoid camelcase. */
    margin: 0;
}
#comment_form { /* Avoid underscores. */
    margin: 0;
}
#c1-xr { /* What is a c1-xr?! Use a better name. */
    margin: 0;
}

Properties and Values

  • Properties ควรเรียงตามลำดับตัวอักษร ยกเว้นในบางกรณี เช่น หากประกาศ width และ height ทั้งคู่ 2 properties นี้ควรอยู่ด้วยกัน
  • Properties ควรตามด้วยเครื่องหมาย Colon (:) และเว้นวรรค 1 วรรค ก่อนระบุค่า
  • ทุก properties และ values ควรเป็นตัวอักษรพิมพ์เล็ก (lowercase) ยกเว้นชื่อฟอนต์หรือ properties เฉพาะบางตัว
  • ใช้ hex code สำหรับการใส่สี และพยายามไม่ใช้รูปแบบ RGB และตัวพิมพ์ใหญ่ (uppercase) และใช้ค่าที่สั้นที่สุดถ้าเป็นไปได้ เช่น ในกรณีให้ค่าสีขาว ควรให้เป็น #fff แทน #FFFFFF
  • ใช้รูปแบบ shorthand (ยกเว้นในบางกรณี) สำหรับค่าใน background, border, font, list-style, margin และ padding (แล้ว shorthand คืออะไร? เดี้ยวจะมีตัวอย่างในท้ายหัวข้อนี้ครับ)

การใช้ prefix ของแต่ละ vendor ก่อน

#selector-1 {
    -moz-box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
    -webkit-box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
    box-shadow: 0px 3px 3px rgba(0, 0, 0, 0.2);
    display: none;
    float: left;
}

ในกรณี properties ของ position (top, right, bottom, left) ควรจัดเป็นกลุ่มโดยนอกเหนือกฏของการเรียงลำดับตัวอักษรไป และใช้ tab ในการ indent เข้าไปอีก 1 ที

#selector-1 {
    font-size: 1em;
    position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
    width: 100px;
    z-index: 1;
}

ถ้าหาก width และ height ถูกประกาศมาด้วยกัน ก็ให้เขาทั้งคู่มาต่อกันเลย โดย height ควรอยู่ติดใต้ weight

#selector-1 {
    width: auto;
    height: auto;
}

ส่วน shorthand คืออะไร?
เช่น ในกรณีที่เราเขียน margin เราไม่จำเป็นต้องเขียนแบบนี้เลย เนื่องจาก margin ค่าจะไล่ตามทิศทางการหมุนของนาฬิกาอยู่แล้ว (clock-wise positions)

.box {
    margin-top: 10px;
    margin-right: 20px; 
    margin-bottom: 10px;
    margin-left: 20px;
}

ซึ่งเราสามารถเขียนแบบนี้ได้เลย ซึ่งทำให้โค้ดเราสั้นลงด้วย

.box {
    margin: 10px 20px 10px 20px;
}

รวมถึงหากเราจะให้ค่า top และ bottom มีค่าเท่ากันคือ 10px และ left และ right มีค่าเท่ากันคือ 20px เราก็สามารถเขียนแบบนี้ได้เลย

.box {
    margin: 10px 20px;
}

หรือในกรณีที่เหมือนด้านบน แต่ไม่ต้องการให้ bottom มีค่าอะไร ก็สามารถทำแบบนี้ได้เลย

.box {
    margin: 10px 20px 0;
}

ลองดูตัวอย่างของการเขียน border นะครับ

.box {
    border-top: 1px;
    border-right: 1px;
    border-bottom: 1px; 
    border-left: 1px;
    border-color: blue;
    border-style: solid}

เราก็สามารถรวมทั้งหมดมาเขียนแบบนี้ได้เลย

.box {
    border: 1px blue solid;
}

Comments

/* Short comments: one line with no trailing space. */
#selector-1 {...

#selector-1 {
    color: #000; /* A short comment can also follow one property/value pair. */
}

/*
For longer, multiple line comments that need more room,
add a newline before and after the comment.
Leave one line of space before the next block.
*/

#selector-1 {...

สำหรับการขึ้นหัวข้อใหม่ (section) ก็ควรเว้นบรรทัด 2 บรรทัดจากส่วนอื่นครับ

#previous-block {
    color: #000;
}


/* =Name of section
-------------------------------------------------------------- */

#selector-1 {...

หวังว่าคงเป็นประโยชน์ไม่มากก็น้อยนะครับ
ขอให้มีความสุขกับการเขียน CSS ครับ : )

รวบรวมและแปลจาก WordPress’s Codex : CSS Coding Standards และ CSS Shorthand

[How to] Level Of Detail (LOD) – X3D(OM) Language [Tutorial in Thai language]

Level Of Detail (LOD) นั้นเป็น Grouping node ตัวหนึ่งในภาษา X3D (หรือเอามาใช้กับ X3DOM ก็ได้ซึ่งใช้ภาษาในการเขียนเป็น X3D เหมือนกัน)
โดย node นี้จะถูกใช้เพื่อการเพิ่มประสิทธิภาพในการเรนเดอร์วัตถุใน Scene เนื่องจากใน Scene ของเรานั้นจะมี Viewpoint อยู่อย่างน้อย node ซึ่งจะเป็นจุดกล้องของเรานั่นเอง ซึ่งมีความห่างในแกน x, y, z กับวัตถุ ซึ่งระยะห่างนี้เราสามารถกำหนดความละเอียดให้กับวัตถุที่เรามองเห็นได้ ลองนึกภาพว่าคุณมองวัตถุที่เห็นไกลๆแล้วคุณเห็นมันไม่ชัด คุณเดินเข้าไปใกล้ขึ้นเรื่อยๆ วัตถุนั้นก็จะชัดขึ้นเรื่อยๆตามลำดับ หากใครที่เคยเล่นเกมแนว 3D มาคงจะพอนึกภาพออกว่าเป็นยังไง
และความละเอียดนั่นเองที่เราจะถูกถึงการเพิ่มประสิทธิภาพของการเรนเดอร์ทั้ง Scene นั้นโดยรวม โดยเฉพาะอย่างยิ่งกับ Scene ที่มีวัตถุหลายๆวัตถุ เราก็ควรจะให้ความสำคัญกับวัตถุที่เราอยู่ใกล้ที่สุด คือ ให้เรามองเห็นสิ่งนั้นชัดที่สุด ละเอียดที่สุด นั่นหมายความว่า ยิ่งความละเอียดเยอะ ยิ่งมี Polygon มาก มีจุดมากนั่นเอง ซึ่งจำนวนจุด (Point) จำนวนรูปสามเหลี่ยม (Triangle) นั่นส่งผลต่อประสิทธิภาพในการเรนเดอร์และค่า Frame rate (หากดู Monitor ของ X3DOM คุณจะเห็นค่านี้แสดงเป็น x FPS โดย x เป็นตัวเลข Floating Point) หรือจากระยะหนึ่ง เข้าไปแล้วให้วัตถุเปลี่ยนไป เข้าไปอีกก็เปลี่ยนไปอีก ก็ได้แล้วแต่เราจะทำครับ

หลังจากพอเข้าใจหลักการคร่าวๆว่าโหนดนี้มีประโยชน์อย่างไร เรามาถึงวิธีการเขียนโหนด LOD กันครับ

<LOD center="0 0 0" range="10 15 20">

	<Group>
		<Shape DEF="Box">
			<Appearance DEF="BlueColor">
				<Material diffuseColor="0.0 0.2 0.8" />
			</Appearance>
			<Box />
		</Shape>
	</Group>

	<Group>
		<Shape>
			<Appearance USE="BlueColor"></Appearance>
			<Cone />
		</Shape>
	</Group>

	<Group>
		<Shape>
			<Appearance USE="BlueColor"></Appearance>
			<Cylinder />
		</Shape>
	</Group>
						
	<WorldInfo info='"null node"' />

</LOD>

จาก Source code
1. เริ่มประกาศโหนด LOD โดยกำหนด Attribute ให้ center มีค่าเป็น 0 0 0 นั่นหมายถึงเริ่มนับตำแหน่งของ LOD ที่จุด 0 0 0 คือจุดกลางของโหนดครับ (ทั้งนี้ไม่นับรวมถึงโหนด Transform นี่ครอบโหนด LOD นี้อีกที) และ range คือระยะห่างจากโหนด LOD ครับ จากตัวอย่างผมให้ระยะห่างเป็น 3 ช่วงคือ 10 15 และ 20 ครับ
2. จากนั้นแบ่งกลุ่มของวัตถุครับ ดังจะเห็นในบรรทัดที่ 3, 12 และ 19 นั่นคือการแบ่งช่วงระยะห่าง โดยนับจาก range คือ ระยะห่างจาก LOD ช่วง 0-10 จะแสดงวัตถุในกลุ่มแรก และมากกว่า 10-15 ก็จะแสดงวัตถุในกลุ่มที่สอง ตามด้วยช่วงมากกว่า 15-20 คือแสดงวันถุในกลุ่มที่สาม และหากระยะห่างจากจุด LOD มากกว่า 20 ขึ้นไป จะแสดงค่าตามบรรทัดที่ 26 ครับ คือบรรทัดนั้นผมกำหนดให้เขาเป็น null node นั่นหมายความว่า จะไม่แสดงอะไรเลย LOD นั้นก็จะหลายเป็นค่าว่างเลยครับ จะไม่มีจุดหรือสามเหลี่ยมอะไรที่ถูกเรนเดอร์ใน LOD นั้นแล้วครับ

จากตัวอย่างผมใช้วิธีเขียนวัตถุโดยใช้ Shape ในการเริ่มสร้างวัตถุง่ายๆขึ้นมาเช่น Box หรือ กล่อง, Cone หรือ กรวย และ Cylinder หรือวัตถุทรงกระบอกโดยให้ค่าเริ่มต้นเป็นค่าพื้นฐาน (Default) ตัววัตถุนั้นๆไป หากต้องการลูกเล่นเพิ่มเริม เราสามารถใช้โหนด Inline ในการเรียกวัตถุจากภายนอกไฟล์มาแทนในกลุ่มนั้นก็ได้ครับ โดยแทนโหนด Shape ไปครับ : )

Get navigation type and set point rendering by using X3DOM Runtime API

First you have to call this method: ready() It is therefore possible to execute custom action by overriding this method in your code:

x3dom.runtime.ready = function()
{
	var id = "x3dom-scene";
	var configure = document.getElementById(id);
	
	/* Default view */
	configure.runtime.showAll();
	getNavigationType(id);
	
	/* =============================================================
	 Arguments:	show (boolean) – true/false to show or hide the debug window
	 Returns: The current visibility status of the debug window (true/false)
	 Displays or hides the debug window. If the parameter is omitted, the current visibility status is returned.
	 ============================================================= */
	configure.runtime.debug(false);
	
	/* =============================================================
	 Arguments:	mode (boolean) – true/false to enable or disable the stats info
	 Returns:The current visibility of the stats info (true/false)
	 Get or set the visibility of the statistics information.
	 If parameter is omitted, this method returns the visibility status as boolean.
	 ============================================================= */
	configure.runtime.statistics(false)
}

That’s your X3DOM scene ID is “x3dom-scene” and your default viewpoint is “showAll”

function getNavigationType(id)
{
	var configure = document.getElementById(id);
	
	var navigationTypeName = configure.runtime.navigationType();
	var currentViewpoint = configure.runtime.viewpoint();
	
	console.log(navigationTypeName);
	console.log(currentViewpoint);
	
	document.getElementById('showNavigationType').innerHTML = navigationTypeName;
	setSpeed(0, id);
}

This method is used to show your current navigation type and your current viewpoint in your X3DOM scene and appear the result to your browser console. and Now, I think you should know how to use X3DOM Runtime API method to your X3DOM scene.

So this is the method that doesn’t public on official page of X3DOM Runtime API, togglePoints method. This method is used to change render type from other to point rendering.

function togglePoint()
{
	var configure = document.getElementById("x3dom-scene");
	configure.runtime.togglePoints();
}

The result example:

When this method was called, your geometry will appear like this.

togglePoints Demo