เริ่มกันที่ KZ ก่อน
KZ-ZST : เป็น driver แบบ dynamic ผสม BA จะมีอยู่ 2-3 lot ที่เสียงไม่เหมือนกัน
> lot1 มีแต่สีดำ ตั้งแต่ออกใหม่ปี 2016 - ต้นปี 2017 ราคาสมัยนั้นค่อนข้างแพง 600+
เสียงเบสหนักที่สุดใน KZ ทั้งหมด ทั้งลึกและแน่น ลูกใหญ่มาก คุณภาพเบสดี กลางแหลมพอดีๆ
ไม่จัด ไม่บาดหู แยกเสียงและรายละเอียดดีแต่ไม่ถึงกับสุด มิติค่อนข้างกว้าง ใช้ BA เบอร์ 1203
> lot2 ปัจจุบันผมไม่มีแล้ว ไม่แน่ใจว่าเป็น defect หรือเปล่า เบสจะลึกแต่ไม่หนักเท่าล็อตอื่น
แหลมไปได้ไกลมากมีแสบแก้วหูเล็กน้อย อันนี้สีดำเหมือนกันได้มากลางปี 2017 หลังกล่องเป็นรูปหู
> lot3 หลังกลางปี 2017 จะเป็นล็อตนี้หมด กล่องข้างหลังใช้รูปเครื่องดนตรีเป่า ราคา 400-500
เสียงจะค่อนข้างสมดุล เบสหนักแต่ความลึกน้อยลง แหลมปลายๆลดลง เสียงกลางหนาขึ้นเล็กน้อย
มิติกว้างที่สุดใน 3 ล็อต รายละเอียดแยกเสียงค่อนข้างขาดเลยทีเดียว ใช้ BA 30095
KZ-ZS5 : เป็นหูฟัง 4 driver มีทั้ง dynamic ขนาด 10mm และ 6.4mm และก็ BA อีก2ตัว
มีมาทั้งหมด 2 lot ข้อแตกต่างคือชนิด driver และการจัดวาง
> lot1 ตั้งแต่ต้นปี 2017 - 8/2017 กล่องดำ ราคา 700-1000
มี BA อยู่ที่ข้างในกับข้างหน้าตะแกรง ใช้ BA เบอร์ 1205 กับ 30095
เสียงส่วนตัวผมว่าดีที่สุดใน KZ ถ้านับจากทุกย่านเสียง เพราะให้ balance ที่ดี stage และมิติ
กว้างที่สุด แยกเสียงและมีรายละเอียดดีที่สุดด้วยเช่นกัน เบสลูกใหญ่กว่า zst lot2-3 แต่ impact
น้อยกว่าพอสมควร เบสลงได้ลึกกว่า zst หน่อยนึง คุณภาพของเบสดีกว่า zst แต่ปริมาณแพ้
> lot2 หลัง 8/2017 เสียงจัดขึ้นมาก โดยเฉพาะเสียงแหลม ราคาพอกันกับ lot1
เพราะเอา BA มาไว้หน้าตะแกรงทั้ง2ตัว ใช้เบอร์ 30095 ทั้งคู่ และเปลี่ยน dynamic 6.4mm ใหม่
เสียงโดยรวมจะ color มากๆ ฟังพวก EDM เหมาะเลย เบสก็หนักกว่าล็อตแรกนิดหน่อย แต่เสียงบาง
กว่าล็อตแรกในภาพรวมเพราะกลางตัวนี้ถอยลงครับ เพราะเบสกับแหลมเด่นขึ้นมา ตัวนี้ขับง่ายกว่า
lot1 เยอะครับปรับนิดเดียวดัง แหลมมากกว่าแต่ผมว่าไม่ละเอียดเหมือน lot1
KZ-ZS3 : driver dynamic ตัวเดียว แต่เสียงนี้คือว่าไม่ได้แพ้ 2 ตัวบนเท่าไหร่ ราคา 300-400
มีล็อตเดียว แนวเสียงเบสหนักรองจาก zst lot1 ลงไม่ลึกเท่า zs5,zst แต่ได้ impact ที่แรงกว่าชัดเจน
กลางแหลมถือว่าดีทีเดียว พอแยกรายละเอียดเสียงได้ แต่แพ้ zs5,zst อยู่ดี แหลมปลายๆมีหายบ้าง
KZ-ES3 : เหมือน zst lot3 ทุกประการ ต่างแค่ body ใช้ dynamic , ba เหมือนกัน ผมฟังเสียงแล้ว
ก็แยกไม่ออก เอามาสลับข้างฟังก็ฟังด้วยกันได้ยังกับรุ่นเดียวกันซะงั้น ราคา 400-500
ต่อมา Ostry kc06a
เสียงต้องบอกว่านิ่งและ balance ดีกว่า kz มากครับด้วยราคาที่แพงกว่าหลายเท่า 1500-2500
เบสหนักกว่าดีกว่าทั้งปริมาณและคุณภาพ กลางแหลมดีให้เสียงที่ธรรมชาติกว่า kz
และจินตนาการถึงเนื้อหนังได้ดีกว่า แต่มิติและทิศทางเสียงการแยกแยะสูสีกับ ZS5
ตัวนี้ถึง driver dynamic ตัวเดียวแต่มีขดลวด 2 ชั้น ทำให้เสียงชนะ BA ของ KZ ได้
Aidisible 2 dynamic driver
เสียงมาทีแรกกลางนำมาค่อนข้างเยอะ นึกว่าเสียงจะไม่ดี พอปรับเบสกับแหลมขึ้น กดกลางลง
เท่านั้นแหละ โอ้โห เสียงสะอาดชัดใสมากๆ กับราคาร้อยสองร้อย สุดๆไปเลย มิติกว้างมากอีกด้วย
แต่เบสตัวนี้พึ่งไม่ได้ เพราะปริมาณน้อยแถมลงไม่ลึก ยังดีที่เบสยังนุ่มไม่แข็งเหมือนตีกระป๋อง
W1 pro
ราคาสองร้อยกว่าบาท เสียงดีกว่าตัวบน 2 driver อีกทั้งๆที่มี driver เดียว การแยกเสียง
มิติดีกว่าตัวบนนิดหน่อย กลางไม่เด่นจนเกินไปแบบตัวบน แล้วก็เบสมากกว่านิดหน่อย
แต่ก็น้อยอยู่ดี โดยรวมลักษณะเสียงคล้ายๆกันเพียงแต่ตัวนี้ไม่ต้องพึ่ง eq แบบตัวบน
J2008 Review แนวเสียง headphone , mobile , PDA , mp3 player and etc
แบ่งปันประสบการณ์ชีวิต สิ่งที่พบเจอ
วันศุกร์ที่ 10 พฤศจิกายน พ.ศ. 2560
วันอาทิตย์ที่ 27 ธันวาคม พ.ศ. 2558
Calibrate proximity sensor in android แก้ปัญหาจอดับหลังโทร
$ su # echo 0 > /sys/devices/virtual/sensors/proximity_sensor/prox_cal # echo 1 > /sys/devices/virtual/sensors/proximity_sensor/prox_cal # chown system:system /efs/prox_cal # chmod 644 /efs/prox_cal # sync # reboot
พิมพ์คำสั่งด้านบนที่ Android Terminal (ต้องไป download terminal ที่ playstore ก่อน)
และ root เครื่องให้เรียบร้อย ไม่งั้นจะใช้คำสั่ง su ไม่ได้
ไม่ต้องพิมพ์ $,# หน้าบรรทัดนะครับ มันคือสัญลักษณ์บอกว่า $ = ทั่วไป # = root access
พิมพ์จบแต่ล่ะบรรทัดเสร็จกด enter ให้ทำงานด้วยนะครับ ไม่ใช่พิมพ์หมดนี้ทีเดียว
วันเสาร์ที่ 17 ตุลาคม พ.ศ. 2558
Tip5 : Linux , Git , Nginx command ที่ใช้บ่อยๆ
======Linux=========
ls -all ดูรายชื่อโฟลเดอร์และไฟล์ทั้งหมด ณ ตำแหน่งที่เราอยู่
cd .. ย้อนกลับโฟล์เดอร์ไป 1 ขั้น
cd [folder_name] เข้าโฟล์เดอร์นั้น
top ดู service ทั้งหมดที่กำลังรันอยู่ และกินเมมโมรี่ไปเท่าไหร่ เมมที่เหลือมีเท่าไหร่
df -h ดูว่าพื้นที่ Storage เหลือเท่าไหร่ ****ถ้าพื้นที่ไม่พอ database ที่อยู่บนเซิฟนั้นจะ error****
du -h --max-depth=1 ดูพื้นที่ของแต่ล่ะไฟล์ โฟลเดอร์
sar ดู IO activity ใน 24ชม ที่ผ่านมา
tail -n 100 [log_name] ดูไฟล์ log 100บรรทัดสุดท้าย
grep -n [find_keyword] [log_name] ดูไฟล์ log ตัดมาเฉพาะบรรทัดที่มีคำ find_keyword อยู่
tail -n 100 [log_name] | grep [keyword] ดูไฟล์ log 100 บรรทัดสุดท้ายที่มี keyword อยู่
sudo chmod 777 [file_name] เปลี่ยน permission file
rm -rf [folder_name] ลบโฟลเดอร์แบบหมดจดแม้จะไม่ใช่โฟลเดอร์ว่าง
iftop -n ดูกิจกรรม network bandwidth (ต้องติดตั้งตัวคำสั่งก่อนถึงใช้ได้)
======My SQL======
mysqld --console เริ่มระบบ
Ctrl+c ออกจากระบบ
mysql -u root -p เข้าสู่ระบบด้วย username = root
mysql -h localhost -u root เข้า localhost ด้วย username = root
show databases แสดงลิตต์ database
======NGINX======
nginx -c C:\nginx\conf\nginx.conf เริ่มระบบ สามารถเข้า localhost ได้หลังใช้
service nginx restart
service php-fpm restart
service memcached restart
======GIT======
git branch เช็คว่าอยู่ brach ไหน
sudo git pull origin ดึง brach
sudo git checkout ย้าย brach
sudo git commit -a -m 'commit_name' comit git
$ git checkout -b [name_of_your_new_branch]
$ git push origin [name_of_your_new_branch]
$ git remote add [name_of_your_remote]
$ git push origin [name_of_your_remote]
$ git fetch [name_of_your_remote]
$ git merge [name_of_your_remote]/develop
$ git branch -d [name_of_your_branch] ลบ local branch
$ git branch -D [name_of_your_branch] ลบ local branch แบบบังคับ
==========PHPMYADMIN remote database=========
ทำให้ phpmyadmin สามารถ access เข้า database จากที่อื่น server อื่นได้ (ปกติลงแล้วมันจะเข้าใช้ localhost)
The settings are stored in config.inc.php at the root of phpMyAdmin's installation directory; e.g. /usr/share/webapps/phpMyAdmin/config.inc.php. Do not dig deeper than that.
(It's the same place where you can find files config.sample.inc.php, ChangeLog, favicon.ico, and such.)
$i++;
$cfg['Servers'][$i]['host'] = 'yourhost.com:3306'; //provide hostname and port if other than default
$cfg['Servers'][$i]['user'] = 'root'; //user name for your remote server
$cfg['Servers'][$i]['password'] = '123456'; //password
$cfg['Servers'][$i]['auth_type'] = 'config'; // keep it as config
ls -all ดูรายชื่อโฟลเดอร์และไฟล์ทั้งหมด ณ ตำแหน่งที่เราอยู่
cd .. ย้อนกลับโฟล์เดอร์ไป 1 ขั้น
cd [folder_name] เข้าโฟล์เดอร์นั้น
top ดู service ทั้งหมดที่กำลังรันอยู่ และกินเมมโมรี่ไปเท่าไหร่ เมมที่เหลือมีเท่าไหร่
df -h ดูว่าพื้นที่ Storage เหลือเท่าไหร่ ****ถ้าพื้นที่ไม่พอ database ที่อยู่บนเซิฟนั้นจะ error****
du -h --max-depth=1 ดูพื้นที่ของแต่ล่ะไฟล์ โฟลเดอร์
sar ดู IO activity ใน 24ชม ที่ผ่านมา
tail -n 100 [log_name] ดูไฟล์ log 100บรรทัดสุดท้าย
grep -n [find_keyword] [log_name] ดูไฟล์ log ตัดมาเฉพาะบรรทัดที่มีคำ find_keyword อยู่
tail -n 100 [log_name] | grep [keyword] ดูไฟล์ log 100 บรรทัดสุดท้ายที่มี keyword อยู่
sudo chmod 777 [file_name] เปลี่ยน permission file
rm -rf [folder_name] ลบโฟลเดอร์แบบหมดจดแม้จะไม่ใช่โฟลเดอร์ว่าง
iftop -n ดูกิจกรรม network bandwidth (ต้องติดตั้งตัวคำสั่งก่อนถึงใช้ได้)
======My SQL======
mysqld --console เริ่มระบบ
Ctrl+c ออกจากระบบ
mysql -u root -p เข้าสู่ระบบด้วย username = root
mysql -h localhost -u root เข้า localhost ด้วย username = root
show databases แสดงลิตต์ database
======NGINX======
nginx -c C:\nginx\conf\nginx.conf เริ่มระบบ สามารถเข้า localhost ได้หลังใช้
service nginx restart
service php-fpm restart
service memcached restart
======GIT======
git branch เช็คว่าอยู่ brach ไหน
sudo git pull origin
sudo git checkout
sudo git commit -a -m 'commit_name' comit git
$ git checkout -b [name_of_your_new_branch]
$ git push origin [name_of_your_new_branch]
$ git remote add [name_of_your_remote]
$ git push origin [name_of_your_remote]
$ git fetch [name_of_your_remote]
$ git merge [name_of_your_remote]/develop
$ git branch -d [name_of_your_branch] ลบ local branch
$ git branch -D [name_of_your_branch] ลบ local branch แบบบังคับ
==========PHPMYADMIN remote database=========
ทำให้ phpmyadmin สามารถ access เข้า database จากที่อื่น server อื่นได้ (ปกติลงแล้วมันจะเข้าใช้ localhost)
The settings are stored in config.inc.php at the root of phpMyAdmin's installation directory; e.g. /usr/share/webapps/phpMyAdmin/config.inc.php. Do not dig deeper than that.
(It's the same place where you can find files config.sample.inc.php, ChangeLog, favicon.ico, and such.)
$i++;
$cfg['Servers'][$i]['host'] = 'yourhost.com:3306'; //provide hostname and port if other than default
$cfg['Servers'][$i]['user'] = 'root'; //user name for your remote server
$cfg['Servers'][$i]['password'] = '123456'; //password
$cfg['Servers'][$i]['auth_type'] = 'config'; // keep it as config
Tip4 : Yii and Php จากประสบการณ์
**************PHP***************
1.ทำให้อัพโหลดไฟล์ได้มากกว่า 5mb
http://www.sutenm.com/%E0%B9%81%E0%B8%81%E0%B9%89%E0%B9%84%E0%B8%82%E0%B9%83%E0%B8%AB%E0%B9%89-wordpress-upload-file/
2.ส่ง post data ไปหน้า page ที่ต้องการ พร้อมรับผลลัพท์ด้วย file_get_content
http://stackoverflow.com/questions/2445276/how-to-post-data-in-php-using-file-get-contents
3.ระบบแจ้งเตือน
http://www.thaicreate.com/community/php-mysql-alert-notify-new-message-notification.html
4.add element to array list
$list = array();
array_push($list, $objWillAdd);
5.การ lmport excel ไฟล์ csv เข้า php
< form enctype="multipart/form-data" method="POST" >
< input name="userfile" type="file" >
< input type="submit" value="Upload" >
< /form >
สำหรับตัวรับไฟล์ก็จะเป็น ภาษา php ดังนี้
if ( isset( $_FILES['userfile'] ) )
{
$csv_file = $_FILES['userfile']['tmp_name'];
if ( ! is_file( $csv_file ) )
exit('File not found.');
if (($handle = fopen( $csv_file, "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
echo $data[0];
echo $data[1];
echo $data[2];
}
fclose($handle);
}
exit( "Complete!" );
}
6.แก้ปัญหาเปิดไฟล์ภาษาไทยแล้วเพี้ยน ครอบด้วย iconv() ด้วยการแปลงจาก TIS-620 เป็น UTF-8 ได้ดังนี้
fopen( iconv('TIS-620',"UTF-8",$file_or_string), "r"))
7.หา sting "are" ใน string $a
strpos($a,'are') !== false //ถ้าเจอคืน true
substr_count($a, 'are') > 0 //ถ้าเจอคืนตำแหน่ง
*************YII*****************
1.นับจำนวน tuple ที่ค้นได้ใน db
$count = Notification::model()->countByAttributes(array(
'user_id'=> Yii::app()->user->uid
));
2.การเพิ่ม FK ใน model
public function relations()
{
return array(
'memberIdMember' => array(self::BELONGS_TO, 'Member', 'member_id_member'),
// 'ชื่อที่ใช้เรียกFK' => array(self::BELONGS_TO, 'Modelของปลายทาง', 'ค่าAtrributeที่ชี้ไปFK'),
);
}
ตัวอย่างเรียกใช้โดย เช่น $advisor->memberIdMember->username
3.get ค่าเป็น array ตามเงื่อนไข
Advisor::model()->findAllByAttributes(array('curriculum_id_curriculum'=>$value));
*************OTHER*************
ปลดล็อค gmail ให้ส่งเมลล์ผ่าน smtp ได้ https://support.google.com/mail/answer/14257
1.ทำให้อัพโหลดไฟล์ได้มากกว่า 5mb
http://www.sutenm.com/%E0%B9%81%E0%B8%81%E0%B9%89%E0%B9%84%E0%B8%82%E0%B9%83%E0%B8%AB%E0%B9%89-wordpress-upload-file/
2.ส่ง post data ไปหน้า page ที่ต้องการ พร้อมรับผลลัพท์ด้วย file_get_content
http://stackoverflow.com/questions/2445276/how-to-post-data-in-php-using-file-get-contents
3.ระบบแจ้งเตือน
http://www.thaicreate.com/community/php-mysql-alert-notify-new-message-notification.html
4.add element to array list
$list = array();
array_push($list, $objWillAdd);
5.การ lmport excel ไฟล์ csv เข้า php
< form enctype="multipart/form-data" method="POST" >
< input name="userfile" type="file" >
< input type="submit" value="Upload" >
< /form >
สำหรับตัวรับไฟล์ก็จะเป็น ภาษา php ดังนี้
if ( isset( $_FILES['userfile'] ) )
{
$csv_file = $_FILES['userfile']['tmp_name'];
if ( ! is_file( $csv_file ) )
exit('File not found.');
if (($handle = fopen( $csv_file, "r")) !== FALSE)
{
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE)
{
echo $data[0];
echo $data[1];
echo $data[2];
}
fclose($handle);
}
exit( "Complete!" );
}
6.แก้ปัญหาเปิดไฟล์ภาษาไทยแล้วเพี้ยน ครอบด้วย iconv() ด้วยการแปลงจาก TIS-620 เป็น UTF-8 ได้ดังนี้
fopen( iconv('TIS-620',"UTF-8",$file_or_string), "r"))
7.หา sting "are" ใน string $a
strpos($a,'are') !== false //ถ้าเจอคืน true
substr_count($a, 'are') > 0 //ถ้าเจอคืนตำแหน่ง
8.microtime(true) is current time in micro second.
9.class ใดๆก็ตามที่มีการสร้าง Object ด้วยการ .getInstance()
จะเรียก class เหล่านั้นว่ามีการเขียนแบบ Singleton
ซึ่งการเขียนลักษณะนี้จะเป็นการสร้าง instance ของ object นั้นขึ้นมาเพียงครั้งเดียวตอนเริ่มโปรแกรม
และให้ class อื่นๆที่ต้องการเรียกใช้ instance ของมันเองเรียกผ่านทาง .getInstance() ครับ
เหตุผลที่ต้องมี singleton เพราะในบางสถานการณ์ การสร้าง object เพียง
ตัวเดียวแล้วให้โปรแกรมทั้งหมดมาใช้ Object ตัวนั้นเพียงตัวเดียวจะมีประโยชน์มากกว่าครับ
เช่น การสร้าง Object ของการเชื่อมต่อฐานข้อมูลที่ต้องใช้พลังงานมากในตอนสร้าง
พอสร้างเสร็จแล้วก็ทำเป็น singleton ไว้ให้ Class อื่นๆ มาเรียกใช้ได้อีกเรื่อยๆครับ
แต่ singleton ก็มีข้อเสียที่เห็นได้ชัดคือ object life time ครับ เพราะ
Object ที่ถูกสร้างขึ้นโดยวิธีนี้จะไม่ถูกทำลายจนกว่าโปรแกรมจะหยุดทำงาน
(ข้อ9อันนี้ไม่ได้เขียนเองครับ นำมาจาก http://www.narisa.com/forums/index.php?showtopic=34733 )
(ข้อ9อันนี้ไม่ได้เขียนเองครับ นำมาจาก http://www.narisa.com/forums/index.php?showtopic=34733 )
10.public function __construct(...) เป็น constructure ของ class ใน php
11.Redis คือ key-value database เหมือนกับ Memcache แต่ต่างกันตรงที่ Redis
นั้นจะทำการบันทึกข้อมูลต่างๆ ลง storage ส่วน memcache จะอยู่ใน ram
นั้นจะทำการบันทึกข้อมูลต่างๆ ลง storage ส่วน memcache จะอยู่ใน ram
12.How to use regular expression for
preg_match('/^(?=.*([0-9]))(?=.*([A-z]))[A-z0-9]{6,12}$/' , $password)
13.เราสามารถเรียกใช้ function ใน class ที่เรา extend เข้ามาได้
โดยการเรียกใช้นั้นเสมือนเราเรียกใช้ function ในคลาสที่เรียก นั้นคือ
function ใน class ที่ extend มานั้น สามารถเรียกใช้ function ใน class ของเราที่เป็นคนเรียกใช้ได้
โดยการเรียกใช้นั้นเสมือนเราเรียกใช้ function ในคลาสที่เรียก นั้นคือ
function ใน class ที่ extend มานั้น สามารถเรียกใช้ function ใน class ของเราที่เป็นคนเรียกใช้ได้
เช่น SerialCodeAbstract ที่ extends TableMapper
ใน SerialCodeAbstract เรียกใช้ static::find() ซึ่งเป็น function ใน TableMapper
จะเสมือนนำ function find() นั้นมารันที่ SerialCodeAbstract นั้นเอง ซึ่งทั้ง 2 คลาสนี้เวลา
เรียกใช้ fuction นั้น จะทำการค้นหา function ในคลาสของผู้ที่เรียก extends ก่อน ในที่นี้คือ
เรียกใช้ fuction นั้น จะทำการค้นหา function ในคลาสของผู้ที่เรียก extends ก่อน ในที่นี้คือ
SerialCodeAbstract นั้นเอง ซึ่งหากไม่มีก็จะไปทำใน fuction ของ TableMapper แทน
(ในตัวอย่าง static:find() นั้นไม่มีใน SerialCodeAbstract แต่มีใน TableMapper
แต่ถ้ามีทั้งคู่ มันจะใช้ในคลาสผู้ที่ extend คือ SerialCodeAbstract นั้นเอง)
แต่ถ้ามีทั้งคู่ มันจะใช้ในคลาสผู้ที่ extend คือ SerialCodeAbstract นั้นเอง)
*************YII*****************
1.นับจำนวน tuple ที่ค้นได้ใน db
$count = Notification::model()->countByAttributes(array(
'user_id'=> Yii::app()->user->uid
));
2.การเพิ่ม FK ใน model
public function relations()
{
return array(
'memberIdMember' => array(self::BELONGS_TO, 'Member', 'member_id_member'),
// 'ชื่อที่ใช้เรียกFK' => array(self::BELONGS_TO, 'Modelของปลายทาง', 'ค่าAtrributeที่ชี้ไปFK'),
);
}
ตัวอย่างเรียกใช้โดย เช่น $advisor->memberIdMember->username
3.get ค่าเป็น array ตามเงื่อนไข
Advisor::model()->findAllByAttributes(array('curriculum_id_curriculum'=>$value));
*************OTHER*************
ปลดล็อค gmail ให้ส่งเมลล์ผ่าน smtp ได้ https://support.google.com/mail/answer/14257
Tip3 : HTML , CSS , Javascript
**************HTML***************
DROP/DOWN MENU http://www.w3schools.com/tags/att_option_value.asp
ROOT URL ใส่ ../ หน้าลิงค์ เช่น "../images/ajax-loader.gif"
Form ถ้าไม่มี action เมื่อ Submit มันจะเรียกตัวมันเองซ้ำ
ทำให้ Input form รองรับเฉพาะไฟล์นามสกุลที่กำหนด
< input type="file" name="file[]" id="filename" accept="image/gif, image/jpeg, image/png, application/pdf, .xlsx, .xls, .doc, .docx" multiple >
************CSS****************
FADEIN/FADEOUT for div http://stackoverflow.com/questions/11679567/using-css-for-fade-in-effect-on-page-load
ทำให้ใส (where 1 is not transparant at all, 0.5 is 50% see-through, and 0 is completely transparent.)
div {
opacity: 0.5;
}
*************JAVA SCRIPT**************
ปัญหาการพัฒนาเว็บส่วนมาก คือ การไม่สามารถโหลดไฟล์ JQuery หรือ .js ได้
(Failed to load resource: the server responded with a status of 404)
ปกติจะเรียกกันแบบ
< script src="js/jquery.min.js" >< /script >
ให้เราเปลี่ยนมาใช้
< script src="<%=ResolveClientUrl("~/js/")%>jquery.min.js" type="text/javascript" >< /script >
1.FADEIN/FADEOUT for id element http://stackoverflow.com/questions/6121203/how-to-do-fade-in-and-fade-out-with-javascript-and-css
2.CHECK FORM VALIDATE(ajax) http://jqueryfordesigners.com/index.html%3Fp=6.html
3.Upload multiple file http://stackoverflow.com/questions/19295746/how-to-upload-multiple-files-using-php-jquery-and-ajax
4.Upload multiple file with interface https://github.com/blueimp/jQuery-File-Upload/wiki
5.Detect when select file in upload buttom
$("#file").change(function(){
//submit the form here
});
6.Auto click buttom
$('#cancel').trigger('click');
7.Click button to do function
< button onclick="myFunction()" >Click me< /button >
8.ส่งค่า POST จาก jquery ให้ไฟล์ php
$('#send').click(function(){
// var clickBtnValue = $(this).val();
var ajaxurl = 'http://mis.cp.eng.chula.ac.th/u54isi/indexTest.php', //ปลายทางรับ post
data = {'action': 'clickBtnValue','fromName':'poo'}; //ข้อมูลที่จะส่งไป post
$.post(ajaxurl, data, function (response) {
// Response div goes here.
alert(response);
});
})
9. เรียกใช้ function ตลอดเวลา ทุกๆ 10000ms หรือ 10วิ
setInterval(functionName, 10000);
10.get ค่าใน html ของ id ต่างๆ
var bar = $('#idname').html();
11.ส่งค่าด้วย post ไปเรียก method ใน url (php) ที่กำหนด ตัวอย่างเรียก get_info แล้วอ่านคืนมาเป็น info
$.ajax({
url: 'ajax',
data: 'action=get_info&value=' + $('#curriculum').val() ,
dataType: 'json',
type: 'post',
success: function (info) {
depart.value = info.depart;
degree.value = info.degree;
fu.value = info.fu;
}
});
12.Foreach ใน javascript
http://blog.levelup.in.th/2010/06/30/javascripts-foreach-foreach-%E0%B9%83%E0%B8%99-javascript/
13.จับว่าเลิก focus element นี้แล้ว
$('#newPassword,#confirmPassword').focusout(function () {
alert('kuy');
if($('#newPassword').val() != $('#confirmPassword').val()) {
// $('#saveChange').disabled = true;
}
});
14.การ disabled ปุ่ม
$("#saveChange").prop('disabled',true);
15.ทำให้ค่าภายใน element เป็น html ที่ต้องการ
$('#sa').html(str_html);
16.
$(document).ready(function () {
//function ที่ต้องการ
});
17.การทำปุ่มอัพไฟล์แบบสวยๆ โดย boostrap
< div class="col-md-2" >
< form enctype="multipart/form-data" method="POST" >
< span class="btn btn-default fileinput-button" style="width: 100%" >
< i class="glyphicon glyphicon-cloud-upload" aria-hidden="true" >< /i>
< span>Import data< /span >
< input type="file" name="studentfile" id="studentfile"/ >
< /span>
< /form>
< /div>
< style>
.fileinput-button {
position: relative;
overflow: hidden;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
font-size: 200px;
direction: ltr;
cursor: pointer;
}
/* Fixes for IE < 8 */
@media screen\9 {
.fileinput-button input {
filter: alpha(opacity=0);
font-size: 100%;
height: 100%;
}
}
< /style>
18.เรียกใช้ฟังก์ชั่นเมื่อเวลาผ่านไป 3000ms
setTimeout(function(){ alert("Hello"); }, 3000);
19.ไม่ให้ form จำรหัส ใส่นี้ในส่วน
< ?php
echo '$("#password").attr("autocomplete", "off");';
echo 'setTimeout('."'".'$("#password").val("");'."'".', 500);';
? >
19. reload
< script type="text/javascript" >
location.reload();
< /script >
DROP/DOWN MENU http://www.w3schools.com/tags/att_option_value.asp
ROOT URL ใส่ ../ หน้าลิงค์ เช่น "../images/ajax-loader.gif"
Form ถ้าไม่มี action เมื่อ Submit มันจะเรียกตัวมันเองซ้ำ
ทำให้ Input form รองรับเฉพาะไฟล์นามสกุลที่กำหนด
< input type="file" name="file[]" id="filename" accept="image/gif, image/jpeg, image/png, application/pdf, .xlsx, .xls, .doc, .docx" multiple >
************CSS****************
FADEIN/FADEOUT for div http://stackoverflow.com/questions/11679567/using-css-for-fade-in-effect-on-page-load
ทำให้ใส (where 1 is not transparant at all, 0.5 is 50% see-through, and 0 is completely transparent.)
div {
opacity: 0.5;
}
*************JAVA SCRIPT**************
ปัญหาการพัฒนาเว็บส่วนมาก คือ การไม่สามารถโหลดไฟล์ JQuery หรือ .js ได้
(Failed to load resource: the server responded with a status of 404)
ปกติจะเรียกกันแบบ
< script src="js/jquery.min.js" >< /script >
ให้เราเปลี่ยนมาใช้
< script src="<%=ResolveClientUrl("~/js/")%>jquery.min.js" type="text/javascript" >< /script >
1.FADEIN/FADEOUT for id element http://stackoverflow.com/questions/6121203/how-to-do-fade-in-and-fade-out-with-javascript-and-css
2.CHECK FORM VALIDATE(ajax) http://jqueryfordesigners.com/index.html%3Fp=6.html
3.Upload multiple file http://stackoverflow.com/questions/19295746/how-to-upload-multiple-files-using-php-jquery-and-ajax
4.Upload multiple file with interface https://github.com/blueimp/jQuery-File-Upload/wiki
5.Detect when select file in upload buttom
$("#file").change(function(){
//submit the form here
});
6.Auto click buttom
$('#cancel').trigger('click');
7.Click button to do function
< button onclick="myFunction()" >Click me< /button >
8.ส่งค่า POST จาก jquery ให้ไฟล์ php
$('#send').click(function(){
// var clickBtnValue = $(this).val();
var ajaxurl = 'http://mis.cp.eng.chula.ac.th/u54isi/indexTest.php', //ปลายทางรับ post
data = {'action': 'clickBtnValue','fromName':'poo'}; //ข้อมูลที่จะส่งไป post
$.post(ajaxurl, data, function (response) {
// Response div goes here.
alert(response);
});
})
9. เรียกใช้ function ตลอดเวลา ทุกๆ 10000ms หรือ 10วิ
setInterval(functionName, 10000);
10.get ค่าใน html ของ id ต่างๆ
var bar = $('#idname').html();
11.ส่งค่าด้วย post ไปเรียก method ใน url (php) ที่กำหนด ตัวอย่างเรียก get_info แล้วอ่านคืนมาเป็น info
$.ajax({
url: 'ajax',
data: 'action=get_info&value=' + $('#curriculum').val() ,
dataType: 'json',
type: 'post',
success: function (info) {
depart.value = info.depart;
degree.value = info.degree;
fu.value = info.fu;
}
});
12.Foreach ใน javascript
http://blog.levelup.in.th/2010/06/30/javascripts-foreach-foreach-%E0%B9%83%E0%B8%99-javascript/
13.จับว่าเลิก focus element นี้แล้ว
$('#newPassword,#confirmPassword').focusout(function () {
alert('kuy');
if($('#newPassword').val() != $('#confirmPassword').val()) {
// $('#saveChange').disabled = true;
}
});
14.การ disabled ปุ่ม
$("#saveChange").prop('disabled',true);
15.ทำให้ค่าภายใน element เป็น html ที่ต้องการ
$('#sa').html(str_html);
16.
$(document).ready(function () {
//function ที่ต้องการ
});
17.การทำปุ่มอัพไฟล์แบบสวยๆ โดย boostrap
< div class="col-md-2" >
< form enctype="multipart/form-data" method="POST" >
< span class="btn btn-default fileinput-button" style="width: 100%" >
< i class="glyphicon glyphicon-cloud-upload" aria-hidden="true" >< /i>
< span>Import data< /span >
< input type="file" name="studentfile" id="studentfile"/ >
< /span>
< /form>
< /div>
< style>
.fileinput-button {
position: relative;
overflow: hidden;
}
.fileinput-button input {
position: absolute;
top: 0;
right: 0;
margin: 0;
opacity: 0;
-ms-filter: 'alpha(opacity=0)';
font-size: 200px;
direction: ltr;
cursor: pointer;
}
/* Fixes for IE < 8 */
@media screen\9 {
.fileinput-button input {
filter: alpha(opacity=0);
font-size: 100%;
height: 100%;
}
}
< /style>
18.เรียกใช้ฟังก์ชั่นเมื่อเวลาผ่านไป 3000ms
setTimeout(function(){ alert("Hello"); }, 3000);
19.ไม่ให้ form จำรหัส ใส่นี้ในส่วน
< ?php
echo '$("#password").attr("autocomplete", "off");';
echo 'setTimeout('."'".'$("#password").val("");'."'".', 500);';
? >
19. reload
< script type="text/javascript" >
location.reload();
< /script >
Tip2 : Android รวมคำสั่ง และปัญหาที่พบบ่อยๆ จากประสบการณ์
============ ERROR ที่พบบ่อย ===============
1 . Gradle DSL method not found: 'runProguard()'
ที่ไฟล์ build.gradle เปลี่ยนดังนี้
runProguard false >> minifyEnabled false
..........................................................................................................................
2.SecurityException: Permission denied (missing INTERNET permission?)
เพิ่มบรรทัดนี้ลงไปที่ AndroidManifest.xml
..........................................................................................................................
3.FATAL EXCEPTION: main android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
1) Don't write network call in Main UI Thread, Use Async Task for that.
2) Write below code into your MainActivity file after setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
..........................................................................................................................
4. Error:(10, 8) error: class MyPageAdapter is public, should be declared in a file named MyPageAdapter.java
ตั้งชื่อไฟล์ java ไม่ตรงกับชื่อ class ให้แก้ให้ตรงกันซะ (ตรง MyPageAdapter ของท่านจะปรากฏไม่เหมือนกัน แล้วแต่ชื่อ)
..........................................................................................................................
5.no such table : message หรือขึ้นว่าไม่มี table
-ให้ตรวจสอบว่าสร้างแล้วยัง ถ้าคำสั่งถูกหมดให้ลองเปลี่ยนชื่อ table ใหม่
-ลองเปลี่ยนเวอร์ชั่น database sqllite ใหม่
..........................................................................................................................
===========TIP ใช้ประจำ=============
1.ส่งตัวแปรข้ามหน้า
ใน MainActivity.java
Intent in = new Intent(MainActivity.this,SecondActivity.class); //มี class ปัจจุบันเป็น MainActivity.java และ class ปลายทาง SecondActivity.java
in.putExtra("key",value); //ส่งตัวแปรพร้อมค่า
startActivity(in); //เปลี่ยนหน้าไปปลายทาง
ใน SecondActivity.java
Intent in = getIntent();
String var = in.getStringExtra("key"); //รับตัวแปร
..........................................................................................................................
2.วันเวลา
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
long today = (new Date()).getTime(); //เวลาขณะนี้
long bday = 0;
String birthday = dpBirthday.getYear() + "-" + (dpBirthday.getMonth()+1) + "-" + dpBirthday.getDayOfMonth();
try {
bday = formatter.parse(birthday).getTime();
} catch (ParseException e) {
e.printStackTrace();
}
long age = (today-bday)/(1000*60*60*24);
..........................................................................................................................
3.JSON
อ่านจากสตริงเดียว
String json = "{\"sName\":\"Sawatdee : Weerachai Nukitram\",\"sEmail\":\"Sawatdee : is_php@hotmail.com\"}";
JSONObject c = new JSONObject(json);
String strResultName = c.getString("sName");
String strResultEmail = c.getString("sEmail");
อ่านจาก array 2d
String strJSON = "[{\"MemberID\":\"1\",\"Name\":\"Weerachai\",\"Tel\":\"0819876107\"}" +
",{\"MemberID\":\"2\",\"Name\":\"Win\",\"Tel\":\"021978032\"}" +
",{\"MemberID\":\"3\",\"Name\":\"Eak\",\"Tel\":\"0876543210\"}]";
JSONArray data = new JSONArray(strJSON);
ArrayList> MyArrList = new ArrayList>();
HashMap map;
for(int i = 0; i < data.length(); i++){
JSONObject c = data.getJSONObject(i);
map = new HashMap();
map.put("MemberID", c.getString("MemberID"));
map.put("Name", c.getString("Name"));
map.put("Tel", c.getString("Tel"));
MyArrList.add(map);
}
อ่านจากหลายมิติ
try
{
String jsonString="";//your json string here
JSONObject jObject= new JSONObject(jsonString).getJSONObject("categories");
Iterator keys = jObject.keys();
while( keys.hasNext() )
{
String key = keys.next();
Log.v("**********", "**********");
Log.v("category key", key);
JSONObject innerJObject = jObject.getJSONObject(key);
Iterator innerKeys = innerJObject.keys();
while( innerKeys.hasNext() )
{
String innerKkey = keys.next();
String value = innerJObject.getString(innerKkey);
Log.v("key = "+key, "value = "+value);
}
}
}
catch (JSONException e)
{ e.printStackTrace(); }
..........................................................................................................................
4.ใส่เส้นคั่นหน้า
android:layout_height="1dip"
android:background="#CCCCCC" />
..........................................................................................................................
5.Layout ต่างๆ
1. Linear Layout เรียงเป็นเส้นตรง แนวนอน หรือ แนวตั้ง โดยใช้คำสั่ง
android:orientation = "horizontal"
android:orientation = "vertical"
2. Relative Layout เรียงตามตำแหน่งอ้างอิงกับ element อื่นๆ ในเลย์เอาต์ หรือ อ้างอิงกับเลย์เอาต์ที่ตัว element นั้นอยู่ โดยใช้คำสั่ง
android:layout_below = "@android:id/text1"
android:layout_toRightOf = "@android:id/checkbox"
3. Frame Layout เป็นการเรียงแบบ stack คือตัวที่สร้างทีหลังจะวางอยู่บนสุด
4. Absolute Layout เป็นการเรียงแบบที่เรากำหนดตำแหน่ง โดยใช้คำสั่ง
android:layout_x="100dp"
android:layout_y="50dp"
5. Table Layout เป็นการเรียงแบบตาราง โดยที่ control แต่ละตัวจะถือเป็น 1 คอลัมน์
โดยจะใช้ .. ครอบแต่ละแถวของตาราง
..........................................................................................................................
6.ใส่ background
android:background="@drawable/bg"
..........................................................................................................................
7.Full Screen app
เปลี่ยน extends เป็น Activity (ห้ามเป็น actionbarActivity) , เพิ่ม 3 บรรทัดนั้นก่อน setContent
public class FullScreen extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
}
}
หรือใช้วิธี
Alternatively you can add
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
to AndroidManifest.xml under
..........................................................................................................................
8.ทำให้ element ภายในพอดี
android:scaleType="centerCrop"
..........................................................................................................................
9.ทำให้ปุ่มกระพริบเป็นอีกภาพเมื่อคลิก
- android:drawable="@drawable/button_pressed" />
- android:drawable="@drawable/button_focused" />
-
แล้ว save ไว้ใน drawable folder เช่น button.xml
ส่วนใน button activity เพิ่ม android:src="@drawable/button"
..........................................................................................................................
10.รับรู้เมื่อปุ่มถูกกด
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
หรือ
android:onClick="selfDestruct"
แล้วเพิ่ม
public void selfDestruct(View view) {
// Kabloey
}
..........................................................................................................................
11. เรียกใช้ JSON
JSONArray arr = new JSONArray(result);
JSONObject jObj = arr.getJSONObject(0);
String date = jObj.getString("NeededString");
..........................................................................................................................
12. ทำให้มีหลายแท็ป
http://www.thaicreate.com/mobile/android-tabhost.html
http://devahoy.com/2014/09/android-tab-with-tabhost-and-actionbar-tab/
http://www.akexorcist.com/2014/11/lets-fragment-view-pager-1.html
ใส่รูปใน tab ด้วย view
http://stackoverflow.com/questions/14535085/add-image-or-style-to-each-tab
..........................................................................................................................
13.การนำภาพมาใช้ เช่น button.jpg จากโฟลเดอร์ Drawable
getResources().getDrawable(R.drawable.button)
..........................................................................................................................
14.เพิ่มสี
Then declare gray in your res\values\strings.xml
#808080
แล้วเรียกใช้ผ่าน @color/grey ได้เลย
..........................................................................................................................
15.การเปลี่ยน string เป็น string[]
String[] ary = "abc".split("");
ary จะเป็น {"a","b","c"}
..........................................................................................................................
16.SQLLITE การลบ
// Delete Data
public long DeleteData() {
// TODO Auto-generated method stub
try {
SQLiteDatabase db;
db = this.getWritableDatabase(); // Write Data
db.delete(TABLE_MEMBER, null, null);
return 0;
} catch (Exception e) {
return -1;
}
}
..........................................................................................................................
17.refresh activity ใหม่
finish();
startActivity(getIntent());
..........................................................................................................................
18.android life cycle
http://startandroid.ru/en/lessons/complete-list/232-lesson-24-activity-lifecycle-example-about-changing-states-with-two-activities.html
..........................................................................................................................
19.kill thread
myService.getThread().interrupt();
..........................................................................................................................
20.Custom list view
http://www.akexorcist.com/2012/09/android-code-custom-list-view.html
..........................................................................................................................
21.การอัพเดท listview
เอาโค้ดนี้ไว้ที่ไหนก็ได้ เช่น เมท็อตรีเฟชร ให้ Thread เรี่ยกใช้ หรือ onResume()
adapter.getData().clear(); //เข้าไปลบ data ใน adapter (ต้องทำ method getData() ไว้ที่ adapter ด้วย)
adapter.setData(m.SelectAllData()); //เข้าไปเพิ่ม data ใน adapter เป็นตัวใหม่ ต้องมีเมท็อตเหมือนกัน
adapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();
..........................................................................................................................
22.ทำให้ Thread สามารถเรียกเมท็อดได้ ให้ครอบด้วย handler
handler.post(new Runnable() {
public void run() {
f.refresh1(); //เมท็อดที่จะเรียก
}
});
..........................................................................................................................
23. Print to console
Log.d("array", a.size() + "");
..........................................................................................................................
24.สร้างตัวแจ้งเตือน
Toast.makeText(getApplicationContext(),
"Sorry", Toast.LENGTH_SHORT).show();
..........................................................................................................................
25.ทำ popup แบบมีหลายตัวเลือก
http://devahoy.com/2014/04/android-dialog-and-custom-dialog-example/#multi-choice-dialog
..........................................................................................................................
=====================hot-key=====================
[[android : pc]]
Home = Home
Back = esc
Power = F7
Menu = F2
VolUp = Ctrl-F5
VolDown = Ctrl-F6
Press ALT+spacebar together, then release and press m. You are now in Move mode. press Enter to exit Move mode.
ออโต้อิมพอต
http://stackoverflow.com/questions/16615038/what-is-the-shortcut-to-auto-import-all-in-android-studio
1 . Gradle DSL method not found: 'runProguard()'
ที่ไฟล์ build.gradle เปลี่ยนดังนี้
runProguard false >> minifyEnabled false
..........................................................................................................................
2.SecurityException: Permission denied (missing INTERNET permission?)
เพิ่มบรรทัดนี้ลงไปที่ AndroidManifest.xml
..........................................................................................................................
3.FATAL EXCEPTION: main android.os.NetworkOnMainThreadException at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork
1) Don't write network call in Main UI Thread, Use Async Task for that.
2) Write below code into your MainActivity file after setContentView(R.layout.activity_main);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
}
..........................................................................................................................
4. Error:(10, 8) error: class MyPageAdapter is public, should be declared in a file named MyPageAdapter.java
ตั้งชื่อไฟล์ java ไม่ตรงกับชื่อ class ให้แก้ให้ตรงกันซะ (ตรง
..........................................................................................................................
5.no such table : message หรือขึ้นว่าไม่มี table
-ให้ตรวจสอบว่าสร้างแล้วยัง ถ้าคำสั่งถูกหมดให้ลองเปลี่ยนชื่อ table ใหม่
-ลองเปลี่ยนเวอร์ชั่น database sqllite ใหม่
..........................................................................................................................
===========TIP ใช้ประจำ=============
1.ส่งตัวแปรข้ามหน้า
ใน MainActivity.java
Intent in = new Intent(MainActivity.this,SecondActivity.class); //มี class ปัจจุบันเป็น MainActivity.java และ class ปลายทาง SecondActivity.java
in.putExtra("key",value); //ส่งตัวแปรพร้อมค่า
startActivity(in); //เปลี่ยนหน้าไปปลายทาง
ใน SecondActivity.java
Intent in = getIntent();
String var = in.getStringExtra("key"); //รับตัวแปร
..........................................................................................................................
2.วันเวลา
DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
long today = (new Date()).getTime(); //เวลาขณะนี้
long bday = 0;
String birthday = dpBirthday.getYear() + "-" + (dpBirthday.getMonth()+1) + "-" + dpBirthday.getDayOfMonth();
try {
bday = formatter.parse(birthday).getTime();
} catch (ParseException e) {
e.printStackTrace();
}
long age = (today-bday)/(1000*60*60*24);
..........................................................................................................................
3.JSON
อ่านจากสตริงเดียว
String json = "{\"sName\":\"Sawatdee : Weerachai Nukitram\",\"sEmail\":\"Sawatdee : is_php@hotmail.com\"}";
JSONObject c = new JSONObject(json);
String strResultName = c.getString("sName");
String strResultEmail = c.getString("sEmail");
อ่านจาก array 2d
String strJSON = "[{\"MemberID\":\"1\",\"Name\":\"Weerachai\",\"Tel\":\"0819876107\"}" +
",{\"MemberID\":\"2\",\"Name\":\"Win\",\"Tel\":\"021978032\"}" +
",{\"MemberID\":\"3\",\"Name\":\"Eak\",\"Tel\":\"0876543210\"}]";
JSONArray data = new JSONArray(strJSON);
ArrayList
HashMap
for(int i = 0; i < data.length(); i++){
JSONObject c = data.getJSONObject(i);
map = new HashMap
map.put("MemberID", c.getString("MemberID"));
map.put("Name", c.getString("Name"));
map.put("Tel", c.getString("Tel"));
MyArrList.add(map);
}
อ่านจากหลายมิติ
try
{
String jsonString="";//your json string here
JSONObject jObject= new JSONObject(jsonString).getJSONObject("categories");
Iterator
while( keys.hasNext() )
{
String key = keys.next();
Log.v("**********", "**********");
Log.v("category key", key);
JSONObject innerJObject = jObject.getJSONObject(key);
Iterator
while( innerKeys.hasNext() )
{
String innerKkey = keys.next();
String value = innerJObject.getString(innerKkey);
Log.v("key = "+key, "value = "+value);
}
}
}
catch (JSONException e)
{ e.printStackTrace(); }
..........................................................................................................................
4.ใส่เส้นคั่นหน้า
android:background="#CCCCCC" />
..........................................................................................................................
5.Layout ต่างๆ
1. Linear Layout เรียงเป็นเส้นตรง แนวนอน หรือ แนวตั้ง โดยใช้คำสั่ง
android:orientation = "horizontal"
android:orientation = "vertical"
2. Relative Layout เรียงตามตำแหน่งอ้างอิงกับ element อื่นๆ ในเลย์เอาต์ หรือ อ้างอิงกับเลย์เอาต์ที่ตัว element นั้นอยู่ โดยใช้คำสั่ง
android:layout_below = "@android:id/text1"
android:layout_toRightOf = "@android:id/checkbox"
3. Frame Layout เป็นการเรียงแบบ stack คือตัวที่สร้างทีหลังจะวางอยู่บนสุด
4. Absolute Layout เป็นการเรียงแบบที่เรากำหนดตำแหน่ง โดยใช้คำสั่ง
android:layout_x="100dp"
android:layout_y="50dp"
5. Table Layout เป็นการเรียงแบบตาราง โดยที่ control แต่ละตัวจะถือเป็น 1 คอลัมน์
โดยจะใช้ .. ครอบแต่ละแถวของตาราง
..........................................................................................................................
6.ใส่ background
android:background="@drawable/bg"
..........................................................................................................................
7.Full Screen app
เปลี่ยน extends เป็น Activity (ห้ามเป็น actionbarActivity) , เพิ่ม 3 บรรทัดนั้นก่อน setContent
public class FullScreen extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main);
}
}
หรือใช้วิธี
Alternatively you can add
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
to AndroidManifest.xml under
..........................................................................................................................
8.ทำให้ element ภายในพอดี
android:scaleType="centerCrop"
..........................................................................................................................
9.ทำให้ปุ่มกระพริบเป็นอีกภาพเมื่อคลิก
แล้ว save ไว้ใน drawable folder เช่น button.xml
ส่วนใน button activity เพิ่ม android:src="@drawable/button"
..........................................................................................................................
10.รับรู้เมื่อปุ่มถูกกด
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
// Perform action on click
}
});
หรือ
android:onClick="selfDestruct"
แล้วเพิ่ม
public void selfDestruct(View view) {
// Kabloey
}
..........................................................................................................................
11. เรียกใช้ JSON
JSONArray arr = new JSONArray(result);
JSONObject jObj = arr.getJSONObject(0);
String date = jObj.getString("NeededString");
..........................................................................................................................
12. ทำให้มีหลายแท็ป
http://www.thaicreate.com/mobile/android-tabhost.html
http://devahoy.com/2014/09/android-tab-with-tabhost-and-actionbar-tab/
http://www.akexorcist.com/2014/11/lets-fragment-view-pager-1.html
ใส่รูปใน tab ด้วย view
http://stackoverflow.com/questions/14535085/add-image-or-style-to-each-tab
..........................................................................................................................
13.การนำภาพมาใช้ เช่น button.jpg จากโฟลเดอร์ Drawable
getResources().getDrawable(R.drawable.button)
..........................................................................................................................
14.เพิ่มสี
Then declare gray in your res\values\strings.xml
แล้วเรียกใช้ผ่าน @color/grey ได้เลย
..........................................................................................................................
15.การเปลี่ยน string เป็น string[]
String[] ary = "abc".split("");
ary จะเป็น {"a","b","c"}
..........................................................................................................................
16.SQLLITE การลบ
// Delete Data
public long DeleteData() {
// TODO Auto-generated method stub
try {
SQLiteDatabase db;
db = this.getWritableDatabase(); // Write Data
db.delete(TABLE_MEMBER, null, null);
return 0;
} catch (Exception e) {
return -1;
}
}
..........................................................................................................................
17.refresh activity ใหม่
finish();
startActivity(getIntent());
..........................................................................................................................
18.android life cycle
http://startandroid.ru/en/lessons/complete-list/232-lesson-24-activity-lifecycle-example-about-changing-states-with-two-activities.html
..........................................................................................................................
19.kill thread
myService.getThread().interrupt();
..........................................................................................................................
20.Custom list view
http://www.akexorcist.com/2012/09/android-code-custom-list-view.html
..........................................................................................................................
21.การอัพเดท listview
เอาโค้ดนี้ไว้ที่ไหนก็ได้ เช่น เมท็อตรีเฟชร ให้ Thread เรี่ยกใช้ หรือ onResume()
adapter.getData().clear(); //เข้าไปลบ data ใน adapter (ต้องทำ method getData() ไว้ที่ adapter ด้วย)
adapter.setData(m.SelectAllData()); //เข้าไปเพิ่ม data ใน adapter เป็นตัวใหม่ ต้องมีเมท็อตเหมือนกัน
adapter.notifyDataSetChanged();
listView.invalidateViews();
listView.refreshDrawableState();
..........................................................................................................................
22.ทำให้ Thread สามารถเรียกเมท็อดได้ ให้ครอบด้วย handler
handler.post(new Runnable() {
public void run() {
f.refresh1(); //เมท็อดที่จะเรียก
}
});
..........................................................................................................................
23. Print to console
Log.d("array", a.size() + "");
..........................................................................................................................
24.สร้างตัวแจ้งเตือน
Toast.makeText(getApplicationContext(),
"Sorry", Toast.LENGTH_SHORT).show();
..........................................................................................................................
25.ทำ popup แบบมีหลายตัวเลือก
http://devahoy.com/2014/04/android-dialog-and-custom-dialog-example/#multi-choice-dialog
..........................................................................................................................
=====================hot-key=====================
[[android : pc]]
Home = Home
Back = esc
Power = F7
Menu = F2
VolUp = Ctrl-F5
VolDown = Ctrl-F6
Press ALT+spacebar together, then release and press m. You are now in Move mode. press Enter to exit Move mode.
ออโต้อิมพอต
http://stackoverflow.com/questions/16615038/what-is-the-shortcut-to-auto-import-all-in-android-studio
วันอาทิตย์ที่ 11 ตุลาคม พ.ศ. 2558
Tip1 : Basic javascript animation PART2
สำหรับตอนที่2 นี้เราก็จะมาดูการประยุกต์ใช้งานจริงด้วยคำสั่งต่างๆนะครับ โดยจากตอนที่แล้ว
ผมได้ทำการอธิบายโค้ดที่เป็นตัวหลักในการควบคุมอนิเมชั่นไปแล้ว วันนี้จะมาอธิบายพวก
คำสั่งที่ใช้งานบ่อยๆ สำหรับใช้ในจาวาสคริปอนิเมชั่นกันนะครับ
1.คำสั่งที่ใช้ควบคุม javascript ที่จำเป็น
var t = setInterval(framerate,500); เป็นการสั่งให้เรียกฟังค์ชั่น (ในที่นี้ชื่อ framerate) ทุกๆ 500ms ไปตลอด
จะหยุดได้ต้องใช้ clearInterval(t); และนี้คือเหตุผลที่ต้องมี var t มารับค่า เพราะจะได้นำมาใช้หยุดคำสั่งได้
note : คำสั่งจะเริ่มทำงานครั้งแรกเมื่อผ่านไป 500ms นับจากคำสั่งถูกรัน ไม่ใช่เริ่มทำงานทันที
คำสั่งต่อมาที่ใช้บ่อยเช่นกันคือ setTimeout(framerate,500); อันนี้ต่างกันคือเรียกใช้เพียงครั้งเดียว เริ่มทำงานหลัง 500ms
สองคำสั่งนี้จำเป็นมากในการควบคุมเวลาที่ทำให้อนิเมชั่นเกิดการเปลี่ยนแปลงตามเวลา
สำหรับ setInterval นั้นนอกจากจะใส่เวลาเป็นตัวเลขเป็นเวลาที่แน่นอนคงที่แล้ว
ยังกำหนดเป็นแบบไม่คงที่ได้ เช่น นับเร็วขึ้นเรื่อยๆ ดูรายละเอียดได้ที่เว็บนี้เลย
http://javascript.info/tutorial/animation
2.คำสั่งเบสิกสุดๆ คือการเปลี่ยนค่า css ของแต่ล่ะ element
เป็นการเปลี่ยนค่าวัตถุ เช่น ขนาด ตำแหน่ง ซ่อน แสดง ขอบ สี โดยเมื่อออกแบบลำดับดีๆ
ก็จะทำให้เกิดการเปลี่ยนแปลงของวัตถุเป็นอนิเมชั่นที่สวยงามได้ โดยใน js เบื้องต้นจะเป็น
document.getElementById("id").style. แล้วตามด้วยคำสั่ง style ต่างๆ เช่น
document.getElementById("id").style.marginTop = "50%";
document.getElementById("id").style.border = "10px solid yellow";
document.getElementById("id".style.backgroundColor = "red";
document.getElementById("id").style.top = "30%";
document.getElementById("id").style.opacity = "0.9";
ถ้าของ Jquery ก็จะสั้นกว่า ตามนี้ http://www.w3schools.com/jquery/jquery_css.asp
ซึ่งคำสั่งเพิ่มเติมสามารถหาได้จาก google เลยครับ
ตัวอย่างโค้ดทำให้การ์ด (html element) เลื่อนขึ้นและโชว์ขอบ และเลื่อนลงซ่อนขอบ
function cardSlideUp(card) {
document.getElementById(card).style.marginTop = "40" + "%";
document.getElementById(card).style.border = "10px solid yellow";
document.getElementById("frame").style.backgroundColor = "red";
setTimeout(function(){ document.getElementById('raid').style.width = "98%"; },20);
setTimeout(function(){ document.getElementById('raid').style.width = "100%"; },200);
}
function cardSlideDown(card) {
document.getElementById(card).style.marginTop = "50" + "%";
document.getElementById(card).style.border = "0px solid yellow";
document.getElementById("frame").style.backgroundColor = "black";
}
เวลาเรียกใช้งานก็จะประมาณนี้
function onClick() { //คำสั่งนี้ถูกเรียกได้หลายวิธี สามารถดูได้ที่ tip part1 บทความที่แล้ว
var scene = 0
function framerate() {
scene++
switch(scene) {
case 1:
cardSlideUp("card"); //500ms แรก เรียกการ์ดขยับขึ้น เป็นการโจมตี โดยต้องมี html element ภาพการ์ดที่มี id = "card" ด้วยในการเรียก
break;
case 2:
cardSlideDown("card"); //500ms ต่อมา โจมตีเสร็จขยับลง
break;
if (scene == 2)
clearInterval(t); //หยุดการทำงานของ setInterval
}
var t = setInterval(framerate,500); //ตั้งเวลาไว้ 500ms หรือครึ่งวินาทีต่อการเปลี่ยนแปลง 1 ครั้ง
}
3.คำสั่งจำพวก Canvas ใช้ร่วมกับ sprite sheet
ถ้าต้องการอนิเมชั่นที่ลื่นไหล สวยงาม สมจริง เช่นท่าเตะของตัวละคร effect สกิลโจมตีต่างๆ
ก็จำเป็นที่จะต้องใช้ sprite sheet ร่วมกับคำสั่ง canvas ล่ะครับ
sprite sheet ก็คือภาพๆนึง ที่รวมการเคลื่อนไหวของตัวละครหรือวัตถุต่างๆ ในทุกๆเฟรมไว้
นั้นเอง เฟรมๆนึงก็จะใช้รูปภาพนึง ดังนั้น sprite image จึงมีภาพเล็กๆหลายภาพ อยู่ในตำแหน่ง
ที่แน่นอน เพราะเวลานำไปใช้งานเราจะทำการดึงภาพเล็กๆนั้นแหละไปทีล่ะภาพ โดยจะเปลี่ยน
ตำแหน่งในการดึงทุกครั้ง เพื่อให้ได้ภาพเคลื่อนไหวที่สวยงามต่อเนื่อง
ตัวอย่างภาพ sprite sheet ของ effect ระเบิด
(http://stackoverflow.com/questions/28201187/working-with-sprite-sheet-animations-in-android)
คราวนี้จะมาอธิบายพร้อม code นะครับ
ขั้นแรก เราต้องมี html element ให้มันแสดงผล canvas ก่อนนะครับ ง่ายๆเลยก็ตัวอย่างเช่น
ก็ไปรันคำสั่งถัดไปแล้ว (async) ก็จะทำให้บางทีนั้นภาพอนิเมชั่นไม่ขึ้น เพราะไม่สามารถหาภาพเจอเนื่องจากโหลดไม่ทัน
วิธีแก้นั้นก็คือให้ทำเป็น img html แล้วโหลดมาไว้ก่อน พร้อมกับซ่อนไว้ ดังตัวอย่างข้างบน หรือถ้าจะใช้ javascript โหลดมาตรงๆล่ะก็ อาจจะต้องมีการหน่วงเวลาด้วยคำสั่ง setTimeout หรือจะใช้ window.onload = function () { ... } ในการรอให้โหลดเสร็จก่อนค่อยรันก็ได้
จากนั้นก็สร้าง javascript สำหรับเรนเดอร์ ดังนี้
function animation() {
var mainAnimationFrame = 0; //เฟรมเริ่มต้นเป็น 0 เหมือนเดิม
var c = document.getElementById("show"); //ต้องนำเข้า canvas html element ที่เราสร้างไว้ในขั้นแรกมาเป็นตัวแปรก่อน
var ctx = c.getContext("2d"); //จากตัวแปร canvas นั้น ก็ใช้คำสั่ง getContext("2d") เพื่อเรียกส่วนการวาดของ canvas ขึ้นมา เก็บไว้ที่ตัวแปร ctx
var skill_img = document.getElementById('skill'); //นำภาพ sprite sheet เข้ามาเก็บ
//ต่อมากำหนดตำแหน่งจุดเริ่มต้นภาพที่จะให้ตัดรูปไปแสดงผลในแต่ล่ะเฟรม โดยสร้างเป็นอาเรย์ javascript
var skill_list = [{'y': '5', 'x': '5'} ,
{'y': '5', 'x': '655'} ,
{'y': '5', 'x': '1305'} ,
{'y': '5', 'x': '1955'}];
function run() {
var id = mainAnimationFrame;
ctx.clearRect(0, 0, 640, 400); //ลบภาพเก่าเฟรมที่แล้ว ถ้าไม่ใส่ภาพจะวาดทับกันไปเรื่อยๆ
ctx.drawImage(
skill_img, //ภาพ sprite ที่โหลดมาไว้ข้างบน
skill_list[id].x, //จุดเริ่มต้นที่วาดภาพในแนวแกน x โดยดูจากอาเรย์ skill_list ตำแหน่งของอาเรย์ตามเฟรมภาพปัจจุบัน
skill_list[id].y, //จุดเริ่มต้นที่วาดภาพในแนวแกน y โดยดูจากอาเรย์ skill_list ตำแหน่งของอาเรย์ตามเฟรมภาพปัจจุบัน
640, //ขนาดรูปต้นฉบับที่จะ crop มาแสดงผล นับจากจุดเริ่มต้นแกน x
400, //ขนาดรูปต้นฉบับที่จะ crop มาแสดงผล นับจากจุดเริ่มต้นแกน y
0, 0, //ตำแหน่ง x,y เริ่มต้นที่จะวาดใน html canvas element
640, //ขนาดรูปแนวแกน x ที่จะวาดลงไปใน canvas
400 //ขนาดรูปแนวแกน y ที่จะวาดลงไปใน canvas
);
mainAnimationFrame += 1; //เพิ่มเฟรมไปเรื่อยๆทีล่ะ 1
if(mainAnimationFrame == 3) //ถ้าหมด sprite ที่จะแสดงผลแล้ว ในที่นี้มี 4 รูป เริ่มจาก 0 1 2 3 ดังนั้นเมื่อถึง 3 ก็คือรูปสุดท้าย จบแล้ว ให้ทำคำสั่งข้างล่าง
{
ctx.clearRect(0, 0, 640, 400); //ลบภาพเก่าที่วาดไว้
clearInterval(r); //จบการแสดงผลโดยจบคำสั่ง setInterval ข้างล่าง
}
}
var r = setInterval(run, 100); //ทำงานทุกๆ 100ms
}
ดูคำอธิบายโค้ดเพิ่มได้ที่
http://www.w3schools.com/tags/canvas_drawimage.asp
จากการแสดงผลอนิเมชั่นด้วย canvas ที่ยกตัวอย่างให้เห็นนั้น เป็นการแสดงผล
อนิเมชั่นจาก sprite image ที่โหลดเข้ามา โดยตัดภาพแต่ล่ะส่วนของ sprite image
(ตามตำแหน่ง x,y ที่เซตใน array skill_list) ไปแสดงผลที่ canvas element ทุกๆ 100ms
ก็เลยจะได้ภาพที่ค่อนข้างลื่นไหล จะเห็นได้ว่าการทำงานนั้นคล้ายกับตัวอย่างโค้ดใน
PART1 อยู่มาก หลักๆคือให้รู้ว่าทุกๆครั้งที่เฟรมนับไปเรื่อยๆนั้นจะต้องทำอะไร อย่างไรบ้าง
จากตัวอย่าง canvas ในที่นี้คือ เฟรมแรกตัดภาพส่วนที่1 ไปแสดง เฟรมต่อไปก็ตัดภาพส่วนที่2 ไปแสดง
ทำแบบนี้ไปเรื่อยๆจนหมดเฟรม ตรงส่วนนี้เราสามารถออกแบบโปรแกรมให้ทำงานตามที่เราต้องการได้
สำหรับการประยุกต์ใช้ตัวอย่างนึงคือ การใช้โค้ดใน part1 นั้น มาเรียกใช้
โค้ดในตัวอย่าง canvas นี้ เช่น
function onClick() {
var scene = 0
function framerate() {
scene++
switch(scene) {
case 1:
cardSlideUp("card"); //500ms แรก เรียกการ์ดขยับขึ้น เป็นการโจมตี โดยต้องมี html element ภาพการ์ดที่มี id = "card" ด้วยในการเรียก
animation(); //สั่งให้วาดอนิเมชั่นด้วย canvas ที่เราได้ออกแบบไว้หลังการ์ดขยับโจมตี
break;
case 2:
cardSlideDown("card"); //500ms ต่อมา โจมตีเสร็จขยับลง
break;
if (scene == 2)
clearInterval(t); //หยุดการทำงานของ setInterval
}
var t = setInterval(framerate,500); //ตั้งเวลาไว้ 500ms หรือครึ่งวินาทีต่อการเปลี่ยนแปลง 1 ครั้ง
}
ผมได้ทำการอธิบายโค้ดที่เป็นตัวหลักในการควบคุมอนิเมชั่นไปแล้ว วันนี้จะมาอธิบายพวก
คำสั่งที่ใช้งานบ่อยๆ สำหรับใช้ในจาวาสคริปอนิเมชั่นกันนะครับ
1.คำสั่งที่ใช้ควบคุม javascript ที่จำเป็น
var t = setInterval(framerate,500); เป็นการสั่งให้เรียกฟังค์ชั่น (ในที่นี้ชื่อ framerate) ทุกๆ 500ms ไปตลอด
จะหยุดได้ต้องใช้ clearInterval(t); และนี้คือเหตุผลที่ต้องมี var t มารับค่า เพราะจะได้นำมาใช้หยุดคำสั่งได้
note : คำสั่งจะเริ่มทำงานครั้งแรกเมื่อผ่านไป 500ms นับจากคำสั่งถูกรัน ไม่ใช่เริ่มทำงานทันที
คำสั่งต่อมาที่ใช้บ่อยเช่นกันคือ setTimeout(framerate,500); อันนี้ต่างกันคือเรียกใช้เพียงครั้งเดียว เริ่มทำงานหลัง 500ms
สองคำสั่งนี้จำเป็นมากในการควบคุมเวลาที่ทำให้อนิเมชั่นเกิดการเปลี่ยนแปลงตามเวลา
สำหรับ setInterval นั้นนอกจากจะใส่เวลาเป็นตัวเลขเป็นเวลาที่แน่นอนคงที่แล้ว
ยังกำหนดเป็นแบบไม่คงที่ได้ เช่น นับเร็วขึ้นเรื่อยๆ ดูรายละเอียดได้ที่เว็บนี้เลย
http://javascript.info/tutorial/animation
2.คำสั่งเบสิกสุดๆ คือการเปลี่ยนค่า css ของแต่ล่ะ element
เป็นการเปลี่ยนค่าวัตถุ เช่น ขนาด ตำแหน่ง ซ่อน แสดง ขอบ สี โดยเมื่อออกแบบลำดับดีๆ
ก็จะทำให้เกิดการเปลี่ยนแปลงของวัตถุเป็นอนิเมชั่นที่สวยงามได้ โดยใน js เบื้องต้นจะเป็น
document.getElementById("id").style. แล้วตามด้วยคำสั่ง style ต่างๆ เช่น
document.getElementById("id").style.marginTop = "50%";
document.getElementById("id").style.border = "10px solid yellow";
document.getElementById("id".style.backgroundColor = "red";
document.getElementById("id").style.top = "30%";
document.getElementById("id").style.opacity = "0.9";
ถ้าของ Jquery ก็จะสั้นกว่า ตามนี้ http://www.w3schools.com/jquery/jquery_css.asp
ซึ่งคำสั่งเพิ่มเติมสามารถหาได้จาก google เลยครับ
ตัวอย่างโค้ดทำให้การ์ด (html element) เลื่อนขึ้นและโชว์ขอบ และเลื่อนลงซ่อนขอบ
function cardSlideUp(card) {
document.getElementById(card).style.marginTop = "40" + "%";
document.getElementById(card).style.border = "10px solid yellow";
document.getElementById("frame").style.backgroundColor = "red";
setTimeout(function(){ document.getElementById('raid').style.width = "98%"; },20);
setTimeout(function(){ document.getElementById('raid').style.width = "100%"; },200);
}
function cardSlideDown(card) {
document.getElementById(card).style.marginTop = "50" + "%";
document.getElementById(card).style.border = "0px solid yellow";
document.getElementById("frame").style.backgroundColor = "black";
}
เวลาเรียกใช้งานก็จะประมาณนี้
function onClick() { //คำสั่งนี้ถูกเรียกได้หลายวิธี สามารถดูได้ที่ tip part1 บทความที่แล้ว
var scene = 0
function framerate() {
scene++
switch(scene) {
case 1:
cardSlideUp("card"); //500ms แรก เรียกการ์ดขยับขึ้น เป็นการโจมตี โดยต้องมี html element ภาพการ์ดที่มี id = "card" ด้วยในการเรียก
break;
case 2:
cardSlideDown("card"); //500ms ต่อมา โจมตีเสร็จขยับลง
break;
if (scene == 2)
clearInterval(t); //หยุดการทำงานของ setInterval
}
var t = setInterval(framerate,500); //ตั้งเวลาไว้ 500ms หรือครึ่งวินาทีต่อการเปลี่ยนแปลง 1 ครั้ง
}
3.คำสั่งจำพวก Canvas ใช้ร่วมกับ sprite sheet
ถ้าต้องการอนิเมชั่นที่ลื่นไหล สวยงาม สมจริง เช่นท่าเตะของตัวละคร effect สกิลโจมตีต่างๆ
ก็จำเป็นที่จะต้องใช้ sprite sheet ร่วมกับคำสั่ง canvas ล่ะครับ
sprite sheet ก็คือภาพๆนึง ที่รวมการเคลื่อนไหวของตัวละครหรือวัตถุต่างๆ ในทุกๆเฟรมไว้
นั้นเอง เฟรมๆนึงก็จะใช้รูปภาพนึง ดังนั้น sprite image จึงมีภาพเล็กๆหลายภาพ อยู่ในตำแหน่ง
ที่แน่นอน เพราะเวลานำไปใช้งานเราจะทำการดึงภาพเล็กๆนั้นแหละไปทีล่ะภาพ โดยจะเปลี่ยน
ตำแหน่งในการดึงทุกครั้ง เพื่อให้ได้ภาพเคลื่อนไหวที่สวยงามต่อเนื่อง
ตัวอย่างภาพ sprite sheet ของ effect ระเบิด
(http://stackoverflow.com/questions/28201187/working-with-sprite-sheet-animations-in-android)
คราวนี้จะมาอธิบายพร้อม code นะครับ
ขั้นแรก เราต้องมี html element ให้มันแสดงผล canvas ก่อนนะครับ ง่ายๆเลยก็ตัวอย่างเช่น
< canvas id="show" width="640px" height="400px" >< /canvas >ต่อมาก็เป็นรูปภาพ sprite sheet ซึ่งให้โหลดมาเป็น html img แล้วทำการซ่อนภาพ ก่อนปิดด้วยวงเล็บปีกกา เช่น
< img id="skill" src="sprite.png" style="display:none" />สำหรับการโหลดภาพเข้ามาใช้ในงานนั้น เนื่องจาก javascript นั้นทำงานแบบไม่รอใคร ไม่รอคำสั่งบรรทัดบนประมวลผลเสร็จ
ก็ไปรันคำสั่งถัดไปแล้ว (async) ก็จะทำให้บางทีนั้นภาพอนิเมชั่นไม่ขึ้น เพราะไม่สามารถหาภาพเจอเนื่องจากโหลดไม่ทัน
วิธีแก้นั้นก็คือให้ทำเป็น img html แล้วโหลดมาไว้ก่อน พร้อมกับซ่อนไว้ ดังตัวอย่างข้างบน หรือถ้าจะใช้ javascript โหลดมาตรงๆล่ะก็ อาจจะต้องมีการหน่วงเวลาด้วยคำสั่ง setTimeout หรือจะใช้ window.onload = function () { ... } ในการรอให้โหลดเสร็จก่อนค่อยรันก็ได้
จากนั้นก็สร้าง javascript สำหรับเรนเดอร์ ดังนี้
function animation() {
var mainAnimationFrame = 0; //เฟรมเริ่มต้นเป็น 0 เหมือนเดิม
var c = document.getElementById("show"); //ต้องนำเข้า canvas html element ที่เราสร้างไว้ในขั้นแรกมาเป็นตัวแปรก่อน
var ctx = c.getContext("2d"); //จากตัวแปร canvas นั้น ก็ใช้คำสั่ง getContext("2d") เพื่อเรียกส่วนการวาดของ canvas ขึ้นมา เก็บไว้ที่ตัวแปร ctx
var skill_img = document.getElementById('skill'); //นำภาพ sprite sheet เข้ามาเก็บ
//ต่อมากำหนดตำแหน่งจุดเริ่มต้นภาพที่จะให้ตัดรูปไปแสดงผลในแต่ล่ะเฟรม โดยสร้างเป็นอาเรย์ javascript
var skill_list = [{'y': '5', 'x': '5'} ,
{'y': '5', 'x': '655'} ,
{'y': '5', 'x': '1305'} ,
{'y': '5', 'x': '1955'}];
function run() {
var id = mainAnimationFrame;
ctx.clearRect(0, 0, 640, 400); //ลบภาพเก่าเฟรมที่แล้ว ถ้าไม่ใส่ภาพจะวาดทับกันไปเรื่อยๆ
ctx.drawImage(
skill_img, //ภาพ sprite ที่โหลดมาไว้ข้างบน
skill_list[id].x, //จุดเริ่มต้นที่วาดภาพในแนวแกน x โดยดูจากอาเรย์ skill_list ตำแหน่งของอาเรย์ตามเฟรมภาพปัจจุบัน
skill_list[id].y, //จุดเริ่มต้นที่วาดภาพในแนวแกน y โดยดูจากอาเรย์ skill_list ตำแหน่งของอาเรย์ตามเฟรมภาพปัจจุบัน
640, //ขนาดรูปต้นฉบับที่จะ crop มาแสดงผล นับจากจุดเริ่มต้นแกน x
400, //ขนาดรูปต้นฉบับที่จะ crop มาแสดงผล นับจากจุดเริ่มต้นแกน y
0, 0, //ตำแหน่ง x,y เริ่มต้นที่จะวาดใน html canvas element
640, //ขนาดรูปแนวแกน x ที่จะวาดลงไปใน canvas
400 //ขนาดรูปแนวแกน y ที่จะวาดลงไปใน canvas
);
mainAnimationFrame += 1; //เพิ่มเฟรมไปเรื่อยๆทีล่ะ 1
if(mainAnimationFrame == 3) //ถ้าหมด sprite ที่จะแสดงผลแล้ว ในที่นี้มี 4 รูป เริ่มจาก 0 1 2 3 ดังนั้นเมื่อถึง 3 ก็คือรูปสุดท้าย จบแล้ว ให้ทำคำสั่งข้างล่าง
{
ctx.clearRect(0, 0, 640, 400); //ลบภาพเก่าที่วาดไว้
clearInterval(r); //จบการแสดงผลโดยจบคำสั่ง setInterval ข้างล่าง
}
}
var r = setInterval(run, 100); //ทำงานทุกๆ 100ms
}
ดูคำอธิบายโค้ดเพิ่มได้ที่
http://www.w3schools.com/tags/canvas_drawimage.asp
จากการแสดงผลอนิเมชั่นด้วย canvas ที่ยกตัวอย่างให้เห็นนั้น เป็นการแสดงผล
อนิเมชั่นจาก sprite image ที่โหลดเข้ามา โดยตัดภาพแต่ล่ะส่วนของ sprite image
(ตามตำแหน่ง x,y ที่เซตใน array skill_list) ไปแสดงผลที่ canvas element ทุกๆ 100ms
ก็เลยจะได้ภาพที่ค่อนข้างลื่นไหล จะเห็นได้ว่าการทำงานนั้นคล้ายกับตัวอย่างโค้ดใน
PART1 อยู่มาก หลักๆคือให้รู้ว่าทุกๆครั้งที่เฟรมนับไปเรื่อยๆนั้นจะต้องทำอะไร อย่างไรบ้าง
จากตัวอย่าง canvas ในที่นี้คือ เฟรมแรกตัดภาพส่วนที่1 ไปแสดง เฟรมต่อไปก็ตัดภาพส่วนที่2 ไปแสดง
ทำแบบนี้ไปเรื่อยๆจนหมดเฟรม ตรงส่วนนี้เราสามารถออกแบบโปรแกรมให้ทำงานตามที่เราต้องการได้
สำหรับการประยุกต์ใช้ตัวอย่างนึงคือ การใช้โค้ดใน part1 นั้น มาเรียกใช้
โค้ดในตัวอย่าง canvas นี้ เช่น
function onClick() {
var scene = 0
function framerate() {
scene++
switch(scene) {
case 1:
cardSlideUp("card"); //500ms แรก เรียกการ์ดขยับขึ้น เป็นการโจมตี โดยต้องมี html element ภาพการ์ดที่มี id = "card" ด้วยในการเรียก
animation(); //สั่งให้วาดอนิเมชั่นด้วย canvas ที่เราได้ออกแบบไว้หลังการ์ดขยับโจมตี
break;
case 2:
cardSlideDown("card"); //500ms ต่อมา โจมตีเสร็จขยับลง
break;
if (scene == 2)
clearInterval(t); //หยุดการทำงานของ setInterval
}
var t = setInterval(framerate,500); //ตั้งเวลาไว้ 500ms หรือครึ่งวินาทีต่อการเปลี่ยนแปลง 1 ครั้ง
}
วันจันทร์ที่ 5 ตุลาคม พ.ศ. 2558
Tip1 : Basic javascript animation PART1
สวัสดีครับ หายไปนานเพราะงานเข้าเยอะมากๆ ช่วงนี้ก็เลยได้เวลาปล่อยของ เอ้ย ปล่อย
ความรู้ที่ได้รับจากการทำงานเป็นโปรแกรมเมอร์ให้เกมๆนึงทางฝั่งญี่ปุ่น โดยส่วนที่ทำให้
ผมชะงักมากสุดก็คือส่วน javascript ที่เป็นอนิเมชั่นนั้นเอง (ปกติผมเป็น backend php)
เอาล่ะ ใน Part1 นี้ผมจะมาอธิบายในส่วนหลักการพื้นฐานที่ควรรู้ก่อน นั้นคือเรื่อง
เวลาที่อนิเมชั่นจะแสดงผล หรือ timeline frame นั้นเอง
Concept
ปกติการรันอนิเมชั่นก็จะมีการกำหนดไว้ว่า ที่เวลาเท่านั้นเท่านี้หลังจาก start จะให้
ทำอะไร วัตถุเคลื่อนไปทางไหน มีอะไรโผล่ขึ้นมา อะไรหายไป และอีกมากมายที่เป็น
การเปลี่ยนแปลงที่ทำให้เกิดเป็นการเคลื่อนไหว หรือ effect ต่างๆ ดังนั้นก็จะต้องมีการ
plan ว่าที่วินาที 1 จะให้ทำอะไร วินาทีต่อมาทำอะไรต่อ เพื่อให้เกิดเป็นภาพอนิเมชั่น
ขึ้นมาในที่สุด บางครั้งอาจเซตเป็น 0.5 วินาที, 0.1 วินาที หรือน้อยจนระดับ ms (millisecond)
แล้วแต่ความ smooth ของภาพ โดยถ้าเซตเป็น 0.5 วินาทีก็หมายความว่า ใน 1 วินาทีที่ผ่านไป
จะมีการเปลี่ยนแปลงเกิดขึ้น 2 ครั้ง และถ้าเซตเป็น 0.1 วินาทีก็มีการเปลี่ยนแปลงเกิดขึ้น 10 ครั้ง
ภาพก็จะ smooth ดูต่อเนื่องมากยิ่งขึ้น ตรงนี้ก็แล้วแต่จุดประสงค์ของแต่ล่ะคนเลยครับ
และนี้คือ basic code พื้นฐานที่เป็นหัวใจสำคัญในการรันอนิเมชั่นใน javascript ครับ
function animation() { //ชื่อฟังค์ชั่นที่คุมเวลาแสดงอนิเมชั่น
var scene = 0 //กำหนด scene หรือฉากแรกเป็น 0
function framerate() {
scene++ //ให้ฉากเปลี่ยนไปเรื่อยๆ โดยเพิ่มทีล่ะ 1
switch(scene) {
case 1:
//ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่1 ตรงนี้
break;
case 2:
//ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่2 ตรงนี้
break;
case 3:
//ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่3 ตรงนี้
break;
if (scene == 3)
clearInterval(t); //ถ้า scene มาถึงฉากสุดท้าย หรือในที่นี้คือ3 ให้หยุดการทำงาน
// กรณีที่อยากให้วน loop เรื่อยๆไม่หยุด ให้เซต scene = 0;
}
var t = setInterval(framerate,1000); //เรียกใช้ function framerate ทุกๆ1000ms
}
จากข้างบนจะเป็น code สำหรับรันอนิเมชั่น โดยเซตเวลาที่ทำอนิเมชั่นต่อครั้ง = 1 วินาที
(1000ms) และมี timeline การรันอนิเมชั่นอยู่ 3 ครั้ง (ในที่นี้ตามจำนวน case 1-3)
โดยฟังค์ชั่นข้างบนนั้นจะมีการเรียกใช้ได้หลายวิธี ตัวอย่าง เช่น
1.รันเมื่อโหลดหน้าเว็บ พวกรูปภาพ ไฟล์ต่างๆ เสร็จแล้ว
window.onload = function () {
animation();
}
2.รันจากฟังค์ชั่นอื่นๆ (สามารถรันจากฟังค์ชั่นอนิเมชั่นตัวอื่นซ้อนอีกทีก็ได้ จะอธิบาย part ต่อไป)
3.รันจาก html element เมื่อคลิก เช่น < img src="xxx.jpg" onclick="animation();">
4.รันจาก html element เมื่อเมาส์ชี้ เช่น < img src="xxx.jpg" onmouseover="animation();">
5.รันจาก html element เมื่อค่าเปลี่ยน เช่น < input type="text" onchange="animation();">
สำหรับวันนี้ก็จะเป็นการอธิบายในส่วนของ concept เบื้องต้นนะครับ
จริงๆในส่วนนี้ก็สามารถนำไปประยุกต์ใช้ได้เยอะ แต่ถ้ายังไม่หนำใจมีตอนหน้าครับ
จะเป็นตัวอย่างการใช้งานจริงแบบง่ายๆ และตอนถัดไปก็จะเป็นการประยุกต์มากขึ้นอีก
ขอบคุณที่ติดตามครับ
ความรู้ที่ได้รับจากการทำงานเป็นโปรแกรมเมอร์ให้เกมๆนึงทางฝั่งญี่ปุ่น โดยส่วนที่ทำให้
ผมชะงักมากสุดก็คือส่วน javascript ที่เป็นอนิเมชั่นนั้นเอง (ปกติผมเป็น backend php)
เอาล่ะ ใน Part1 นี้ผมจะมาอธิบายในส่วนหลักการพื้นฐานที่ควรรู้ก่อน นั้นคือเรื่อง
เวลาที่อนิเมชั่นจะแสดงผล หรือ timeline frame นั้นเอง
Concept
ปกติการรันอนิเมชั่นก็จะมีการกำหนดไว้ว่า ที่เวลาเท่านั้นเท่านี้หลังจาก start จะให้
ทำอะไร วัตถุเคลื่อนไปทางไหน มีอะไรโผล่ขึ้นมา อะไรหายไป และอีกมากมายที่เป็น
การเปลี่ยนแปลงที่ทำให้เกิดเป็นการเคลื่อนไหว หรือ effect ต่างๆ ดังนั้นก็จะต้องมีการ
plan ว่าที่วินาที 1 จะให้ทำอะไร วินาทีต่อมาทำอะไรต่อ เพื่อให้เกิดเป็นภาพอนิเมชั่น
ขึ้นมาในที่สุด บางครั้งอาจเซตเป็น 0.5 วินาที, 0.1 วินาที หรือน้อยจนระดับ ms (millisecond)
แล้วแต่ความ smooth ของภาพ โดยถ้าเซตเป็น 0.5 วินาทีก็หมายความว่า ใน 1 วินาทีที่ผ่านไป
จะมีการเปลี่ยนแปลงเกิดขึ้น 2 ครั้ง และถ้าเซตเป็น 0.1 วินาทีก็มีการเปลี่ยนแปลงเกิดขึ้น 10 ครั้ง
ภาพก็จะ smooth ดูต่อเนื่องมากยิ่งขึ้น ตรงนี้ก็แล้วแต่จุดประสงค์ของแต่ล่ะคนเลยครับ
และนี้คือ basic code พื้นฐานที่เป็นหัวใจสำคัญในการรันอนิเมชั่นใน javascript ครับ
function animation() { //ชื่อฟังค์ชั่นที่คุมเวลาแสดงอนิเมชั่น
var scene = 0 //กำหนด scene หรือฉากแรกเป็น 0
function framerate() {
scene++ //ให้ฉากเปลี่ยนไปเรื่อยๆ โดยเพิ่มทีล่ะ 1
switch(scene) {
case 1:
//ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่1 ตรงนี้
break;
case 2:
//ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่2 ตรงนี้
break;
case 3:
//ใส่ function หรือ code ที่ต้องการให้ run เมื่อถึงวินาทีที่3 ตรงนี้
break;
if (scene == 3)
clearInterval(t); //ถ้า scene มาถึงฉากสุดท้าย หรือในที่นี้คือ3 ให้หยุดการทำงาน
// กรณีที่อยากให้วน loop เรื่อยๆไม่หยุด ให้เซต scene = 0;
}
var t = setInterval(framerate,1000); //เรียกใช้ function framerate ทุกๆ1000ms
}
จากข้างบนจะเป็น code สำหรับรันอนิเมชั่น โดยเซตเวลาที่ทำอนิเมชั่นต่อครั้ง = 1 วินาที
(1000ms) และมี timeline การรันอนิเมชั่นอยู่ 3 ครั้ง (ในที่นี้ตามจำนวน case 1-3)
โดยฟังค์ชั่นข้างบนนั้นจะมีการเรียกใช้ได้หลายวิธี ตัวอย่าง เช่น
1.รันเมื่อโหลดหน้าเว็บ พวกรูปภาพ ไฟล์ต่างๆ เสร็จแล้ว
window.onload = function () {
animation();
}
2.รันจากฟังค์ชั่นอื่นๆ (สามารถรันจากฟังค์ชั่นอนิเมชั่นตัวอื่นซ้อนอีกทีก็ได้ จะอธิบาย part ต่อไป)
3.รันจาก html element เมื่อคลิก เช่น < img src="xxx.jpg" onclick="animation();">
4.รันจาก html element เมื่อเมาส์ชี้ เช่น < img src="xxx.jpg" onmouseover="animation();">
5.รันจาก html element เมื่อค่าเปลี่ยน เช่น < input type="text" onchange="animation();">
สำหรับวันนี้ก็จะเป็นการอธิบายในส่วนของ concept เบื้องต้นนะครับ
จริงๆในส่วนนี้ก็สามารถนำไปประยุกต์ใช้ได้เยอะ แต่ถ้ายังไม่หนำใจมีตอนหน้าครับ
จะเป็นตัวอย่างการใช้งานจริงแบบง่ายๆ และตอนถัดไปก็จะเป็นการประยุกต์มากขึ้นอีก
ขอบคุณที่ติดตามครับ
วันเสาร์ที่ 15 สิงหาคม พ.ศ. 2558
[ ANDRIOD ] ไมค์ไม่ดัง แก้ได้ด้วยการปรับค่า mixer_paths.xml , Fix low mic volumn by change value in mixer_paths.xml
**Root request**
ใช้ ES Explorer
1.เข้าไปที่ menu -> Root explorer กดเปิด open แล้วจะเด้งเมนู popup ขึ้นมา
2.เลือก R/W แล้วที่เส้นทาง(path) สองอันแรก (/ กับ /system) ให้เลือก RW
3.เข้าไปที่ system->etc->mixer_paths.xml
4.มองหาบรรทัดดังนี้
//speaker mode call
//normal mode call
//headphone mode call
แล้วแก้ค่าข้างใน เช่น="DEC5 Volume" value="60" /> แก้เป็นให้มากกว่า 60
แก้โดยคลิกที่ : มุมบนขวา เลือก แก้ไข (edit) หลังจากแก้ไขแล้วกดย้อนกลับ จะมีให้บันทึก
5.restart จบ ลองทดสอบดู เท่านี้ไมค์ฝั่งเราก็ดังขึ้นแล้ว ฝ่ายคู่สนทนาจะได้ยินเราชัดขึ้น
*****Backup ไฟล์ต้นฉบับเสมอ เพราะอาจทำให้ mic ไม่ทำงานได้ถ้าเซตผิด******
ใช้ ES Explorer
1.เข้าไปที่ menu -> Root explorer กดเปิด open แล้วจะเด้งเมนู popup ขึ้นมา
2.เลือก R/W แล้วที่เส้นทาง(path) สองอันแรก (/ กับ /system) ให้เลือก RW
3.เข้าไปที่ system->etc->mixer_paths.xml
4.มองหาบรรทัดดังนี้
แล้วแก้ค่าข้างใน เช่น
แก้โดยคลิกที่ : มุมบนขวา เลือก แก้ไข (edit) หลังจากแก้ไขแล้วกดย้อนกลับ จะมีให้บันทึก
5.restart จบ ลองทดสอบดู เท่านี้ไมค์ฝั่งเราก็ดังขึ้นแล้ว ฝ่ายคู่สนทนาจะได้ยินเราชัดขึ้น
*****Backup ไฟล์ต้นฉบับเสมอ เพราะอาจทำให้ mic ไม่ทำงานได้ถ้าเซตผิด******
วันจันทร์ที่ 18 สิงหาคม พ.ศ. 2557
How to upload image from windows phone 8 to web server. c# อัพโหลดรูปในวินโดว์โฟนขึ้นเซริฟ์เวอร์
Step การอัพโหลดรูปขึ้น server ใน windows phone for c#
1.)ใช้ชุดคำสั่ง PhotoChooserTask เลือกรูปในเครื่องแล้วเก็บเป็น bitmapImage
หรือใช้ photoCameraCapture ถ้าต้องการให้ถ่ายรูปทันทีแล้วเ ก็บเป็นภาพแทน
http://www.geekchamp.com/tips/how-to-use-photochoosertask-and-cameracapturetask-in-windows-phone
2.)นำรูป bitmapImage มาเข้ารหัส แปรเป็น byte[]
public static byte[] ImageToBytes(BitmapImage img)
{
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(img);
System.Windows.Media.Imaging.Extensions.SaveJpeg(btmMap, ms, img.PixelWidth, img.PixelHeight, 0, 100);
img = null;
return ms.ToArray();
}
}
เรียกใช้เช่น byte[] bit = ImageToBytes(img);
http://stackoverflow.com/questions/22241480/convert-bitmap-image-to-byte-array-windows-phone-8
3.)นำ byte[] มาเข้ารหัส base64 แปลเป็น String ความยาวมหาศาล
string strImg = Convert.ToBase64String(bit);
4.)ส่ง String ไปสู่ server เข้าไปที่ไฟล์ upload.php
ดูวิธีได้ที่ www.thaicreate.com/mobile/windows-phone-add-insert-data-into-web-server.html
5.)ที่ไฟล์ upload.php รับและแปล String กลับเป็น image ด้วย base64.decode
แล้วเซฟภาพเข้าสู่ไดเรกทอรี่ของเว็บ ไซด์ ในที่นี้ save ลงใน webURL/image
php code
define('UPLOAD_DIR', 'image/');
$img = $_POST['sIMG'];
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.jpeg';
$success = file_put_contents($file, $data);
1.)ใช้ชุดคำสั่ง PhotoChooserTask เลือกรูปในเครื่องแล้วเก็บเป็น bitmapImage
หรือใช้ photoCameraCapture ถ้าต้องการให้ถ่ายรูปทันทีแล้วเ
http://www.geekchamp.com/tips/how-to-use-photochoosertask-and-cameracapturetask-in-windows-phone
2.)นำรูป bitmapImage มาเข้ารหัส แปรเป็น byte[]
public static byte[] ImageToBytes(BitmapImage img)
{
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(img);
System.Windows.Media.Imaging.Extensions.SaveJpeg(btmMap, ms, img.PixelWidth, img.PixelHeight, 0, 100);
img = null;
return ms.ToArray();
}
}
เรียกใช้เช่น byte[] bit = ImageToBytes(img);
http://stackoverflow.com/questions/22241480/convert-bitmap-image-to-byte-array-windows-phone-8
3.)นำ byte[] มาเข้ารหัส base64 แปลเป็น String ความยาวมหาศาล
string strImg = Convert.ToBase64String(bit);
4.)ส่ง String ไปสู่ server เข้าไปที่ไฟล์ upload.php
ดูวิธีได้ที่ www.thaicreate.com/mobile/windows-phone-add-insert-data-into-web-server.html
5.)ที่ไฟล์ upload.php รับและแปล String กลับเป็น image ด้วย base64.decode
แล้วเซฟภาพเข้าสู่ไดเรกทอรี่ของเว็บ
php code
define('UPLOAD_DIR', 'image/');
$img = $_POST['sIMG'];
$img = str_replace('data:image/jpeg;base64,', '', $img);
$img = str_replace(' ', '+', $img);
$data = base64_decode($img);
$file = UPLOAD_DIR . uniqid() . '.jpeg';
$success = file_put_contents($file, $data);
สมัครสมาชิก:
บทความ (Atom)