Archive for Tháng Một, 2011
Tìm hiểu về HTML5 – Phần IV (tiếp)
Thực hành: Vẽ đồ thị với HTML5 Canvas API
Trong phần trước chúng ta đã cùng nhau tìm hiểu về HTML5 Canvas API. Tuy nhiên, cách dễ nhất để biết lập trình là phải thực hành nó! Bài viết này sẽ trình bày cách ứng dụng Canvas API để thực hiện một công việc phổ biến: vẽ đồ thị.
Bước 1: khai báo một canvas trong HTML. Lưu ý thuộc tính id của tag <canvas> là cần thiết để dễ dàng tương tác sau này.
<!DOCTYPE html> <head> <meta charset="utf-8”/> <title>Worm Chart</title> </head> <body> <canvas id=“chart” width=“800” height=“600”></canvas> </body> </html>
Bước 2: JavaScript sẽ được sử dụng để làm việc với canvas. Do đó chúng ta cần thêm cặp tag <script> sau vào trong phần <head> của trang web.
<script type=“text/javascript”> </script>
Bước 3: khai báo biến để chứa dữ liệu cho đồ thị. Trong ví dụ này chúng ta sử dụng một mảng thể hiện thông tin về doanh thu của từng tháng. Đặt đoạn code sau trong tag <script>
var data = new Array(12); data[0] = “Jan,280”; data[1] = “Feb,320”; data[2] = “Mar,240”; data[3] = “Apr,470”; data[4] = “May,310”; data[5] = "Jun,260"; data[6] = "Jul,510"; data[7] = "Aug,310"; data[8] = "Sep,400"; data[9] = "Oct,270"; data[10] = "Nov,340"; data[11] = "Dec,440";
Bước 4: định nghĩa hàm vẽ đồ thị.
function graph() { // lấy về phần tử canvas để thao tác var canvas = document.getElementById(‘chart’); // kiểm tra phần tử canvas trả về là hợp lệ if (canvas && canvas.getContext) { var context = canvas.getContext(‘2d’); drawChart(context, data, 50, 50, (canvas.height - 20), 100); } }
Hàm graph() chỉ thực hiện một công việc đơn giản: lấy về phần tử canvas được khai báo trong trang web theo id của nó. Sau khi đảm bảo rằng canvas này là hợp lệ, graph() truy vấn context của canvas và chứa nó trong biến context. Đối tượng context này sẽ rất quan trọng trong các hoạt động vẽ sau này. Chi tiết về cách vẽ đồ thị được giao lại cho hàm tiện ích drawChart() xử lý.
function drawChart(context, data, startX, colWidth, chartHeight, interval) { // vẽ hai trục X, Y của đồ thị context.lineWidth = “1.0”; var startY = 580; drawLine(context, startX, startY, startX, 30); drawLine(context, startX, startY, 770, startY); context.lineWidth = "0.0”; var maxValue = 0;
// lấy dữ liệu từ mảng và vẽ các cột đồ thị for (var i = 0; i < data.length; i++) { var values = data[i].split(“,”); var name = values[0]; var height = parseInt(values[1]);
if (parseInt(height) > parseInt(maxValue))
maxValue = height;
context.fillStyle = “azure”; drawRectangle(context, startX + (i * colWidth) + i, (chartHeight - height), colWidth, height, true); // vẽ tên cột trên trục X context.textAlign = “left”; context.fillStyle = “#00F”; context.fillText(name, startX + (i * colWidth) + i, chartHeight + 10, 200); }
// vẽ các mốc trên trục Y var numMarkers = Math.ceil(maxValue / interval); context.textAlign = “right”; context.fillStyle = “#F0F”; var markerValue = 0;
for (var i = 0; i < numMarkers; i++)
{
context.fillText(markerValue, (startX - 5),(chartHeight - markerValue), 20);
markerValue += interval;
}
}
function drawLine(context, startx, starty, endx, endy)
{
context.beginPath();
context.moveTo(startx, starty);
context.lineTo(endx, endy);
context.closePath();
context.stroke();
}
function drawRectangle(context, x, y, w, h, fill)
{
context.beginPath();
context.rect(x, y, w, h);
context.closePath();
context.stroke();
if (fill)
context.fill();
}
Có lẽ cũng không cần giải thích gì thêm về đoạn code trên. Sau khi hoàn tất, công việc cuối cùng chỉ là gọi hàm graph() để vẽ đồ thị.
Bước 5: gọi hàm graph trong sự kiện OnLoad của trang web.
<body onLoad=“graph();”>
Thế là xong! Bây giờ bạn chỉ cần lưu trang web lại và mở nó lên với một trình duyệt hỗ trợ HTML5 (tôi sử dụng Google Chrome 8 để thử nghiệm). Kết quả nhận được sẽ tương tự như sau:
* Source code:
Download file HTML hoàn chỉnh chứa các đoạn code trong bài ở đây
* Mục lục:
Hỗ trợ Multi-touch và Ink trong Silverlight
Posted by worm.NET in Silverlight on Tháng Một 16, 2011
Silverlight được coi như nền tảng phát triển của Microsoft cho các ứng dụng internet giàu khả năng tương tác (RIA). Không chỉ dừng lại trên trình duyệt, Silverlight cũng đang ngấp nghé thị trường thiết bị di động, đặc biệt là điện thoại thông minh. Để có thể thành công trên lĩnh vực này, chắc chắn Silverlight cần phải cung cấp cho người dùng những cách tương tác mới (ngoài chuột và bàn phím!). Thật may là bạn có thể tìm thấy trong Silverlight tất cả các hỗ trợ cần thiết cho các công nghệ đang “nóng” hiện nay, bao gồm Multi-touch và Ink.
Multi-touch
Multi-touch (hay cảm ứng đa chạm) là công nghệ cho phép người sử dụng giao tiếp với thiết bị thông qua các cử động của ngón tay và màn hình cảm ứng. Mặc dù single-touch xuất hiện trên thị trường đã lâu, nhưng sự ra đời của multi-touch mới thực sự đem lại những trải nghiệm thú vị: bạn có thể sử dụng các cử điệu của ngón tay để thực hiện các thao tác phức tạp (như phóng to, thu nhỏ) mà trước đây không thể làm được với single-touch. Siverlight hỗ trợ Multi-touch từ phiên bản 3 và cung cấp một giao diện lập trình để làm việc với công nghệ này.
Multi-touch về cơ bản là một phương pháp nhập (input), mà điều đầu tiên cần nhắc đến khi nói về xử lý nhập là các sự kiện nhập. Trong Silverlight, sự kiện chính mà ta cần quan tâm là FrameReported của lớp Touch. Touch là lớp static, do đó ta có thể đăng kí sự kiện này như sau:
Touch.FrameReported += new TouchFrameEventHandler(Touch_FrameReported);
Nếu đã quen với cơ chế xử lý sự kiện trong C#, bạn hẳn có thể nhận ra một chút khác biệt: FrameReported là một sự kiện static và không gắn với bất kì đối tượng giao diện nào (trái với các sự kiện như Click luôn gắn với đối tượng Button cụ thể). Sự kiện này được phát sinh mỗi khi phần cứng gửi tín hiệu đến môi trường thực thi. Thời điểm phát sinh cụ thể tùy thuộc vào trình điều khiển phần cứng mà bạn sử dụng. Nhưng tóm lại thì sau khi đăng kí sự kiện trên, bạn đã có thể bắt đầu nghĩ đến chuyện xử lý nó được rồi! Phương thức xử lý sự kiện này cũng tương tự như các phương thức xử lý sự kiện thông thường khác:
void OnTouchFrameReported(object sender, TouchFrameEventArgs e) { string str = ""; foreach (TouchPoint tp in e.GetTouchPoints(this)) { str += string.Format("{0}; ", tp.Position); } MessageBox.Show(str); }
Không có gì khó khăn để đoán được ý nghĩa của đoạn code trên là hiển thị ra màn hình vị trí của các điểm chạm (touch point). Điều đáng lưu ý ở đây nằm ở tham số thứ hai của phương thức. Đây là một tham số thuộc kiểu TouchFrameEventArgs, cung cấp cho ta rất nhiều thông tin hữu ích. Trong đó phải kể đến đầu tiên là hai phương thức GetPrimaryTouchPoint() và GetTouchPoints(). GetPrimaryTouchPoint() trả về điểm chạm đầu tiên, trong khi GetTouchPoints() trả về một tập hợp tất cả các điểm chạm. Các điểm chạm này lại được thể hiện bởi lớp TouchPoint, gồm các thuộc tính quan trọng sau:
- Position: tọa độ x, y của điểm chạm. Tọa độ này có thể là tương đối so với một phần tử giao diện nào đó (nếu bạn truyền phẩn tử đó vào GetPrimaryTouchPoint() hoặc GetTouchPoints()) hoặc tuyệt đối (nếu bạn truyền null cho hai phương thức này).
- Size: kích thước của điểm chạm, phản ánh mức độ nhấn tay mạnh hay nhẹ.
- Action: mô tả hành động của người dùng, có thể là Down (khi vừa nhấn tay xuống), Up (khi vừa nhả tay) hoặc Move (di chuyển ngón tay trên màn hình)
- TouchDevice: thiết bị cung cấp thông tin về điểm chạm. Thuộc tính DirectlyOver của TouchDevice trả về phần tử giao diện nằm trên cùng tại vị trí điểm chạm. Thuộc tính này chủ yếu để đảm bảo tính tương thích với WPF.
Ink
Ink là một loại nội dung đặc biệt dưới dạng các nét vẽ được tạo ra bởi chuột hoặc một thiết bị trỏ có dạng giống cây bút (còn gọi là stylus). Silverlight cho phép thu thập loại nội dung này một cách dễ dàng với lớp InkPresenter. Thông tin về ink sẽ được lưu trữ dưới dạng Stroke. Ta có thể khai báo một InkPresenter trong XAML như sau:
<Grid x:Name="grid"> <InkPresenter x:Name="inkPresenter" Background="White"/> </Grid>
Tương tự như với Multi-touch, để làm việc với Ink, bạn sẽ cần phải quan tâm đến các sự kiện. Thông thường, trong sự kiện MouseLeftButtonDown, ta sẽ tạo một đối tượng Stroke mới, và xây dựng Stroke này khi người dùng rê thiết bị (con trỏ hoặc stylus…) trên InkPresenter với sự kiện MouseMove, cuối cùng kết thúc trong sự kiện MouseLeftButtonUp. Ý tưởng này được minh họa trong đoạn code sau:
private Stroke _stroke; public MainPage() { InitializeComponent(); inkPresenter.MouseLeftButtonDown += new MouseButtonEventHandler(inkPresenter_MouseLeftButtonDown); inkPresenter.MouseMove += new MouseEventHandler(inkPresenter_MouseMove); inkPresenter.MouseLeftButtonUp += new MouseButtonEventHandler(inkPresenter_MouseLeftButtonUp); } private void inkPresenter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { inkPresenter.CaptureMouse(); _stroke = new Stroke(e.StylusDevice.GetStylusPoints(inkPresenter)); inkPresenter.Strokes.Add(_stroke); } private void inkPresenter_MouseMove(object sender, MouseEventArgs e) { if (_stroke != null) { _stroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(inkPresenter)); } } private void inkPresenter_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) { inkPresenter.ReleaseMouseCapture(); _stroke = null; }
Ngoài ra, lớp Stroke còn có nhiều thuộc tính cho phép định dạng nét vẽ (màu sắc, kích thước…). Bạn có thể tự tìm hiểu thêm
Kết luận:
Xử lý nhập là một phần quan trọng không thể thiếu của mọi ứng dụng. Với việc hỗ trợ các công nghệ tương tác mới nhất như Multi-touch và Ink, Silverlight đã cung cấp một môi trường phát triển lý tưởng cho mọi nển tảng: dù là web, desktop, hay di động. Silverlight không chỉ đơn giản hóa công việc của các lập trình viên, mà còn góp phần mang đến cho người dùng những trải nghiệm mới đầy thú vị.
