IT

เรียก Instagram API ดึงภาพรอบพิกัด lat, lng ด้วย JavaScript

7 October 2015

[อัพเดท 2018: บทความนี้ผมเขียนไว้หลายปีแล้ว อาจใช้ไม่ได้ในปัจจุบัน]

ตอนที่ผมเรียนคอร์ส udacity FEND มี project นึงที่ผมเรียกภาพจาก instagram API มาแสดง วันนี้เอา code ส่วนนั้นมาแชร์กันครับ ผิดถูกประการใดแนะนำด้วยนะครับ ^.^ เรื่อง promise นี่ผมก็ยังไม่ค่อยเข้าใจนัก

Project

Project ที่จะทำในวันนี้หน้าตาเป็นแบบนี้ครับ

ig-project-01

มี spec คือ เมื่อคลิกที่ชื่อ location ที่เราต้องการ จะไปดึงภาพ instagram ที่อยู่รอบๆ latitude, longtiude นั้นมา โดยภาพที่จะดึงได้ เจ้าของภาพต้องตั้งเป็น public (เราไม่สามารถดึงภาพของ private account มาไม่ได้ครับ)

ตัวอย่าง

Instagram API

ก่อนอื่นเลยเราต้องสมัครใช้งาน instagram API ก่อนครับที่เว็บ Instagram Developer สำหรับเรื่องนี้ พี่ DayDev เขียนไว้ละเอียดกว่าผม ลองเข้าไปอ่านกันได้ที่ Instagram API เบื้องต้นกับการดึงรูปภาพมาแสดงโดยใช้ Tags อย่างง่าย หรือใครอยากอ่านภาษาอังกฤษ ลองไปที่ Tutsplus ได้ครับ Introduction to the Instagram API

ig-project-02

อธิบายคร่าวๆ นะครับ คือ Instagram API จะมี endpoint url ให้เราหลายๆ แบบ แต่ละแบบจะต้องการ Authentication ต่างๆ กันไป ลองเข้าไปดูได้ที่ Instagram API Endpoints ซึ่งถ้าดูจาก Location Endpoints แล้ว เราต้องใช้ Access Token

https://api.instagram.com/v1/locations/search?lat=48.858844&lng=2.294351&access_token=ACCESS-TOKEN

ซึ่งการจะได้ Access Token มา ทำได้ 2 แบบ คือ server-side และ client-side เพื่อความง่าย ในโปรเจคท์นี้ผมจึงใช้ client-side ไปก่อนนะครับ (แต่มันจะมีข้อจำกัดหลายๆ อย่างในวิธีนี้) ซึ่งสร้างได้โดยวิธีต่อไปนี้

  1. เข้าไปแล้วสมัครสมาชิก เลือก Register new Client ID กรอกข้อมูลอะไรไป
  2. ตรง Valid redirect URIs ตั้งเป็น http://localhost ไปก่อน
  3. ไม่ต้องติ๊กช่อง Disable implicit OAuth
  4. ใส่ url ต่อไปนี้ลงไปใน address bar “https://instagram.com/oauth/authorize/?client_id=[CLIENT_ID_HERE]&redirect_uri=http://localhost&response_type=token” โดยเปลี่ยน [CLIENT_ID] ให้เป็น Client ID ที่เขาให้มาในข้อ 1
  5. สังเกตที่ url เราจะได้ access token มาครับ “http://localhost/#access_token=[ACCESS_TOKEN]” เก็บ Token นี้ไว้ใช้ต่อไป

เริ่มกันเลย

1. เตรียม HTML, CSS, JS ไฟล์เบื้องต้น

ข้อนี้ไม่ขอบรรยายเยอะนะครับ ผมใช้ library เป็น bootstrap และ jQuery ส่วน HTML ก็มีโครงสร้างไม่กี่อย่าง ที่เหลือเป็น JavaScript เรียกภาพมา append เข้าไปใน DOM เฉยๆ ครับ ไฟล์มีอยู่สามไฟล์

ig-project-03

index.html

style.css


2. เตรียมข้อมูลวัด

สเตปแรกคือเตรียมข้อมูล latitude และ longtitude ของวัดก่อน อันนี้ต้องไปหาเอาเอง (ยกเว้นจะเรียก Google Maps API ให้หาให้นะครับ แต่ก็จะเพิ่มความซับซ้อน)

app.js


3. bind Event ให้เรียก function เวลาเราคลิกที่ลิสท์

app.js

แต่ละ li จะมี class ‘.location-list-item’ อยู่ ใช้ class นั้นเป็น selector เมื่อคลิกที่ element นั้น

  • ได้ index ของ element ที่เราคลิก จากนั้นนำ index นั้นไปเอาค่า lat, lng ที่เราเตรียมไว้มาจาก placeData array
  • เรียก function ‘getIgPhoto’ โดยใช้ lat, lng ของ placeData นั้นเป็น arguments

4. AJAX call ครั้งแรก

ในการจะทำ project นี้ เราต้องเรียก instagram API 2 ครั้งครับ เมื่อเราใส่ latitude และ longtitude ไป เราจะได้ Array ของ location-id กลับมา จากนั้นจึงนำ location-id นั้นไปเรียกอีกครั้ง จึงจะได้ image object จริงๆ กลับมา

อธิบายหลักการก็คือ instagram เก็บข้อมูลสถานที่ไว้ในฐานข้อมูลชุดหนึ่ง เวลาเราอัพรูปใน instagram แล้วเราเลือกให้แสดง location ด้วย ตัว location ต่างๆ ที่ขึ้นมาให้เลือกนี่แหละครับคือพิกัดที่ instagram เก็บข้อมูลไว้ สำหรับ location search endpoint ก็คือเราให้พิกัด latitude(LAT) longtitude(LNG) ไป แล้วกำหนดระยะทาง(DISTANCE) รอบๆ พิกัดนี้ instagram จะไปดึง location ทั้งหมดในฐานข้อมูล ที่อยู่รอบๆ พิกัดนี้ในระยะที่เรากำหนดมา เช่น รอบพิกัด 1,000 เมตร รอบวัดพระแก้ว อาจจะมี 15 location เป็นต้น

ig-project-04

แสดง location search endpoints

เช่น ในตัวอย่างของ API Docs คือ ถ้าให้พิกัดฟอไอเฟลไป ก็จะได้ response กลับมาแบบนี้

ig-project-05

เพราะฉะนั้น code เราจึงเป็นแบบนี้

กลับไปดูที่ API docs กันอีกครั้ง ถ้าเราอยากได้รูปที่อยู่รอบๆ location-id หนึ่งๆ เราต้องเตรียม endpoint format ดังต่อไปนี้

ig-project-06

นำ object ที่ response กลับมา มาสร้าง array ของ url สำหรับการ call ครั้งที่สอง

เมื่อเสร็จขั้นตอนนี้ ใน locationURLlist ของเราจะมี utl ใน format นี้ ‘https://api.instagram.com/v1/locations/{location-id}/media/recent?access_token=ACCESS-TOKEN’ จำนวน 10 url


5. AJAX call ครั้งที่สอง

ต้องบอกก่อนว่าเรื่อง promise นี่ผมไม่แม่นจริงๆ นะครับ แฮ่ๆ อธิบายตามที่เข้าใจก็คือ เราต้องการ call AJAX พร้อมๆ กันหลายอันแบบขนาน (parallel) เราจึงใช้ $.when แต่เนื่องจาก $.when รับค่าเป็น deferred object เราจึงต้อง map แต่ละ url ให้ return มาเป็น array ของ deferred object แล้ว apply มาใส่ $.when จากนั้นเมื่อ done แล้วจึงทำขั้นตอนต่อไป ซึ่งไม่มีอะไรซับซ้อนแล้วหลังจากตรงนี้

ลองอ่านเพิ่มเติมได้ที่ link ต่อไปนี้นะครับ

ก็หมดแล้วครับ


6. สรุปภาพรวมของ JS ทั้งไฟล์

app.js ก็อปไปแล้วเปลี่ยนตรง [ACCESS_TOKEN] ก็ใช้ได้เลยครับ


อยากทำอะไรมากไปกว่านี้

เนื่องจากที่ผมทำเป็นแค่โปรเจคท์คร่าวๆ เฉยๆครับ ถ้าอยากทำมากกว่านี้มีไอเดียหลายอย่างที่ทำได้


Search bar

เราไม่ต้องเตรียมข้อมูลพิกัดไว้ก่อน แต่เราสามารถให้ user ป้อน address ที่ต้องการแล้วเราใช้ Google Maps Geocoding API เปลี่ยนเป็น latitude longtitude ได้ ลองดูเพิ่มเติมได้ครับ

ig-project-07

สุดท้ายจะออกมาเหมือนเว็บนี้ Worldcam


Cache

เนื่องจากตอนนี้ทุกครั้งที่เราคลิก เว็บจะต้องเรียก instagram API ใหม่ทุกครั้ง ซึ่งมันทำให้ช้า และตัวเว็บก็ไม่ได้ต้องการความ real-time ขนาดนั้น ดังนั้นถ้าเรา cache รูปไว้ซักระยะหนึ่งก่อน เช่น load แค่ครั้งแรกครั้งเดียว ก็คงจะเร็วขึ้นครับ


Sort images by time

เนื่องจากเราเรียก AJAX ตาม location-id เพราะฉะนั้น response ที่กลับมาจึงเรียงตาม location-id แต่ response ที่กลับมาก็มี created_time เป็น property อยู่แล้ว ดังนั้นก่อนจะ  append เข้าไปใน DOM เราสามารถ sort object ใน array ได้ ลองดู Array.prototype.sort() ครับ


Display image in Google Maps

เนื่องจากแต่ละ location-id มันก็มี latitude, longitude ของตัวเองอยู่แล้ว จริงๆ ก็เอามา pin ใน google maps ได้

และอื่นๆ อีกมากมายครับ


ปิดท้าย

คือถึงจะเขียนมาจนจบแล้ว ผมก็ยังนึก use case ของ project นี้จริงๆ ไม่ค่อยออกครับ ออกแนว gimmick มากกว่า เพราะ ที่ใช้บ่อยจริงๆ น่าจะเป็นดึง instagram image ตาม hashtag มากกว่า งาน event ใช้กันพรึ่บแน่นอน 55 แต่ก็ไม่เป็นไรครับ ถือว่าฝึกฝีมือ หวังว่าจะเป็นประโยชน์นะครับ 🙂

You Might Also Like

No Comments

Leave a Reply