Mvc ve SignalR İle Hatırlatıcı Notlar Bölüm1
Selamlar;
Bugün benim bolca ihtiyaç duyduğum:) sizin de işine yarayacağını düşündüğüm SignlR ve Mvc 6.0 ile Web üzerine hatırlatıcı notlar yazıp, bunları ekran üzerinde istediğimiz yere oynatacağız. Daha sonra sayfaya geri geldiğimiz de ilgili notlar, önceden ekran üzerinde belirlediğimiz yerlerde karşımıza çıkacak. Bir de yeni eklenen notlar, sayfada olan diğer kullanıcılar için de socket teknolojisi kullanılarak sayfada belirecek ve yeri değiştirildiğinde diğer client ekranlarında da hareket edicek.
Öncelikle bir Asp.Net Mvc projesi yaratılır. Sonra yaratılan Index.cshtml sayfasına bir toolbar konur. Ilgili toolbar üzerinde yapıştırılacak kağıt rengi ve içine yazılacağı notun bulunduğu “txtNote” id’li bir textarea nesnesi vardır. Aynı div içine “draggable” id’li bir başka div konarak, yaratılan yeni noteların bu div’in içinde oluşturulması sağlanır.
1 2 3 4 5 6 7 8 9 10 11 12 |
<div id="container"> <div id="menu" style="background-image: url('/Menu/Background2.png');height:70px; z-index:999999"> <img src="~/Menu/MenuRed.png" class="menu" onclick="AddNote(1)" /> <img src="~/Menu/MenuYellow.png" class="menu" onclick="AddNote(2)" /> <img src="~/Menu/MenuBlue.png" class="menu" onclick="AddNote(3)" /> <img src="~/Menu/MenuGreen.png" class="menu" onclick="AddNote(4)" /> <textarea rows="3" cols="30" id="txtNote" style="font-size:medium; color:cornflowerblue;font-family:'Times New Roman';">Yazmak İstediğiniz Notu Belirtiniz!</textarea> </div> <br /> <div id="draggable"> </div> </div> |
Yukarıdaki kodda da görüldüğü gibi ilgili resimler tıklanınca “AddNote()” function’ı çağrılmıştır. Herbir renge denk gelen parametre de ilgili function’a gönderilmiştir. Burada amaç seçilen renge göre ilgili text’i o renkteki kağıt resim ile birlikte render edip yeni bir resim olarak ekrana basmaktır.
Index.cshtml(AddNote(id)): Aşağıdaki functionda’da görüldüğü gibi “PostMessage()” methoduna ilgili parametreler gönderilerek post edilip, “Note” klasörü altında yeni oluşmuş resim ismi geri dönülerek “draggable” divinin içine html string olarak basılır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
function AddNote(id) { switch (id) { case 1: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'red' }).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } case 2: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'yellow' }).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } case 3: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'blue' }).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } case 4: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'green' }).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } } $("#txtNote").val(""); $("#txtNote").focus(); } |
Şimdi sıra geldi ilgili resim ve yazıdan yeni bir resim oluşturmaya.
HomeController.cs(PostMessage()): Aşağıda görüldüğü gibi seçilen renge göre ilgili text, resim üzerine “DrawString” ile farklı font renkleri ile yazılmıştır. Ve daha sonra oluşturulan yeni resim “Note” klasörünün altına yeni bir “Guid” ismi ile kaydedilmiştir. Son olarak oluşturulan yeni resim ismi string olarak geri dönülmüştür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public string PostMessage(string Note, string color) { Bitmap bmp = new Bitmap(Server.MapPath("/papers/" + color + ".png")); RectangleF rectf; if (color != "yellow") rectf = new RectangleF(40, 40, 200, 300); else rectf = new RectangleF(50, 60, 300, 300); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = SmoothingMode.AntiAlias; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.PixelOffsetMode = PixelOffsetMode.HighQuality; if (color == "red") g.DrawString(Note, new Font("Comic Sans MS", 18, FontStyle.Bold), Brushes.White, rectf); else if (color == "yellow") g.DrawString(Note, new Font("Comic Sans MS", 31, FontStyle.Bold), Brushes.Red, rectf); else if (color == "green") g.DrawString(Note, new Font("Comic Sans MS", 35, FontStyle.Bold), Brushes.Blue, rectf); else if (color == "blue") g.DrawString(Note, new Font("Comic Sans MS", 18, FontStyle.Bold), Brushes.Black, rectf); g.Flush(); Guid imgName = Guid.NewGuid(); bmp.Save(Server.MapPath("/notes/" + imgName + ".png")); return imgName.ToString(); } |
Yukarıdaki animasyonda da görüldüğü gibi yeni eklenen notlar sürüklenebilmektedir. Öncelikle gelin bunu bir inceleyelim. Sayfaya eklenen notların class’ı=”paper” dır. Ve her resim div’e eklendiğinde “init()” function’ı çağrılmaktadır.
Index.cshtml(init()): “$(“.paper”).draggable()” ile eklenen resimlerin sürüklenebilmesi sağlanmıştır. Sürüklenme işi bitince(stop:function()) resmin son kordinatı olan “left ve top” alınıp “coordinates()” function’ına gönderilir.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
function init() { $(".paper").draggable({ start: function () { //coordinates(this); }, stop: function () { var _left = $(this)[0].style.left.replace("px", ""); var _top = $(this)[0].style.top.replace("px", ""); var left = _left; var top = _top; coordinates(top, left, this.src); } }); $(".paper").dblclick(function () { $.post("/Home/DeleteImage", { imgUrl: this.src }).done(function (imgName) { var object = $('img[src*="' + imgName + '"]'); object[0].remove(); }); }); } |
Index.cshtml(coordinates()): Burada amaç ilgili resmlerin hareket ettirildikten sonra son kordinatlarnın saklanıp sayfaya tekrardan gelindiğinde ilgili notların son bırakıldıkları noktadan çıkarılmasıdır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var coordinates = function (_top, _left, src) { var name = src; console.log(src); var top = _top; var left = _left; var connectionID = 0; console.log("top:" + top + " left:" + left); $.post("/Home/ChangeImageName", { Name: name, Cordinates: top + "x" + left, ConnectionID: connectionID }).done(function (newSrc) { var _newSrc = newSrc.split('æ')[0]; var _name = newSrc.split('æ')[1]; var object = $('img[src*="' + _name + '"]'); object[0].src = "http://localhost:34544/Notes/" + _newSrc; }); } |
Ben kordinatların kaydedilmesi için burada biraz radikal bir yol seçtim ve Database veya Cookie kullanmadım. Yukarıdaki kodda görüldüğü gibi “ChangeImageName()” methoduna image’in ismi, son kordinatları ve daha sonra bahsediceğimiz connectionID parametreleri gönderilmektedir. Öncelikle ilgili methodu inceleyelim, daha sonra post işlemi tamamlandığında neler oluyor onu görelim.
HomeController.cs(ChangeImageName()): Aşağıda görüldüğü gibi 1. konumdan 2.konuma gelen image isminin sonuna kordinat bilgisi konulmuştur. Burdan da anlaşılacağı gibi resimin ekran üzerindeki konumu isminde saklanmıştır. Resim hareket ettirildiğinde isminin sonuna yeni konum bilgisi “_” ayracı ile ayrılarak konulmuş ve sonra dosya ismi “MoveTo()” methodu yeni kordinat ismi ile değiştirilerek hem eski hem de yeni ismi birleştirilip geri dönülmüştür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public string ChangeImageName(string Name, string Cordinates,string ConnectionID) { string NewName = Path.GetFileNameWithoutExtension(Name); FileInfo fInfo = new FileInfo(Server.MapPath("/Notes/"+NewName+".png")); if (NewName.Contains('_')) { NewName = NewName.Split('_')[0] + "_" + Cordinates+".png"; } else { NewName = NewName + "_" + Cordinates+".png"; } fInfo.MoveTo(Server.MapPath("/Notes/" + NewName)); return NewName+"æ"+Path.GetFileNameWithoutExtension(Name); } |
Geri dünülen resim bilgileri sayesinde aşağıda görüldüğü gibi öncelikle jquery ile ilgili resim, eski yani hareket ettrilmeden önceki konum bilgisine sahip olan “src” attribute ile bulunmuş ve yeni yol bilgisi yani en son getirldiği kordinat bilgisine sahip “src” değeri ile değiştirilmiştir.
1 2 3 4 |
var _newSrc = newSrc.split('æ')[0]; var _name = newSrc.split('æ')[1]; var object = $('img[src*="' + _name + '"]'); object[0].src = "http://localhost:34544/Notes/" + _newSrc; |
Index.cshtml(document.ready()): Sayfa ilk yüklendiğinde önceden yüklenen resimlerin en son kordinatları ile ekrana basılması için “GetImages()” methoduna ajax post yapılır. Geriye “json” bir data döner. Dönen listede resimlerin “src” bilgileri bulunmaktadır. Ilgili Url bilgisinde resmin kordinat bilgisi de bulunmaktadır. “left ve top” bilgileri “imageList[]” dizisi içinden pars edilip, herbir resim kendi kordinatında “<div id=’draggable’>” div’inin altına basılır. Ayrıca “txtNote” içine bilgilendirici yazı yazılması ve odaklanıldığında temizlenmesi yine “document.ready()” function’ı altında tanımlanmaktadır.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
$(document).ready(function () { $('#txtNote').focus(function () { if ($('#txtNote').val().trim() == 'Yazmak İstediğiniz Notu Belirtiniz!') { $('#txtNote').val(''); } }).blur(function () { if ($('#txtNote').val().trim() == '') { $('#txtNote').val('Yazmak İstediğiniz Notu Belirtiniz!') } }); $.ajax({ url: '/Home/GetImages', type: 'post', dataType: 'json', success: function (imageList) { for (var i = 0; i < imageList.length; i++) { if (imageList[i].ImageName.split('_').length > 1) { var _top = imageList[i].ImageName.split('_')[1].split('x')[0]; var _left = imageList[i].ImageName.split('_')[1].split('x')[1].replace('.png', ''); $('#draggable').append("<img src='/Notes/" + imageList[i].ImageName + "' class='paper' style='top:" + _top + "px; left: " + _left + "px; position:absolute'/>"); } else { $('#draggable').append("<img src='/Notes/" + imageList[i].ImageName + "' class='paper' style='position:absolute' />"); } }; init(); } }); }); |
HomeController.cs(GetImages()): Aşağıda “Index.cshtml” sayfasının yüklenmesinden sonra, önceden yazılmış resim şeklindeki notelar eklenme zamanına göre, “Notes” kalsörü içinde tek tek gezilerek isimleri “Images” sınıfına ait bir listeye eklenir. Ve bu işlemin sonunda ilgili liste “Json” olarak dönülür.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
class Images { public string ImageName { get; set; } } public JsonResult GetImages() { DirectoryInfo directory = new DirectoryInfo(Server.MapPath("/Notes")); List<Images> ImageList = new List<Images>(); foreach (FileInfo file in directory.GetFiles().OrderBy(img=>img.CreationTime)) { Images img = new Images(); img.ImageName = file.Name; ImageList.Add(img); } return Json(ImageList, JsonRequestBehavior.AllowGet); } |
Bu bölümde son olarak eklenen noteların silinmesi özelliğini inceleyeceğiz. Resimler çift tıklanıldığında silinmesi işlemi Index.cshtml tarafında “init()” function’ı altında aşağıdaki gibi tanımlanmıştır. Eklenen tüm resimler, kendilerine atanmış “.paper” class’ı sayesinde yakalanıp “dblclick()” olayında “DeleteImages()” methoduna post işlemi yapılmıştır. İlgili methoddan silinecek resmin “src” yolu geri dönmekte ve daha sonra ilgili resim “src” yoluna göre bulunup ekrandan silinmekte yani “remove()” edilmektedir.
Index.cshtml(init()):
1 2 3 4 5 6 |
$(".paper").dblclick(function () { $.post("/Home/DeleteImage", { imgUrl: this.src, ConnectionID: connectionID }).done(function (imgName) { var object = $('img[src*="' + imgName + '"]'); object[0].remove(); }); }); |
HomeController(DeleteImage()): Gönderilen resimler ilgili “Notes” folder’ı altından silinerek, dosya ismi geri dönülür.
1 2 3 4 5 6 7 8 |
public string DeleteImage(string imgUrl,string ConnectionID) { string fileName = Path.GetFileName(imgUrl); FileInfo file = new FileInfo(Server.MapPath("/Notes/" + fileName)); file.Delete(); return fileName; } |
Bu zamana kadar belli bir renkte kağıda yazı yazıp ilgili note’u ekrana basmayı gördük. Ayrıca bu noteları ekranın istediğimiz bir yerine sürükleyebildik. Ve her sürüklemede ismini değiştirip ilgili kordinatları resim yolunun sonuna ekledik. Böylece ilgili sayfaya tekrar gelindiğinde notları bıraktığımız konumda kordinatları başka bir storage’a kaydetmeden bulabildik. Ayrıca ilgili resimler çıft tıklayarak silebildik. 2. Bölümde SignalR socket teknolojisi kullanılarak hareket ettirilen bir note’un tüm clientlarda animatif olarak hareket ettirilmesini, yeni eklenen ve silinen noteların o andaki tüm clientlarda gösterilmesi yada silinmesini hep beraber inceleyeceğiz. En sonunda da uygulamamızı Azure publish edeceğiz.
Geldik bir makalenin daha sonuna. Makalenin devamında görüşmek üzere hoşçakalın.
HomeController.cs(Full):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.IO; using System.Linq; using System.Threading.Tasks; using System.Web; using System.Web.Mvc; namespace Reminder.Controllers { class Images { public string ImageName { get; set; } } public class HomeController : Controller { // GET: Home public ActionResult Index() { return View(); } public JsonResult GetImages() { DirectoryInfo directory = new DirectoryInfo(Server.MapPath("/Notes")); List<Images> ImageList = new List<Images>(); foreach (FileInfo file in directory.GetFiles().OrderBy(img=>img.CreationTime)) { Images img = new Images(); img.ImageName = file.Name; ImageList.Add(img); } return Json(ImageList, JsonRequestBehavior.AllowGet); } public string DeleteImage(string imgUrl,string ConnectionID) { string fileName = Path.GetFileName(imgUrl); FileInfo file = new FileInfo(Server.MapPath("/Notes/" + fileName)); file.Delete(); return fileName; } public string ChangeImageName(string Name, string Cordinates,string ConnectionID) { string NewName = Path.GetFileNameWithoutExtension(Name); FileInfo fInfo = new FileInfo(Server.MapPath("/Notes/"+NewName+".png")); if (NewName.Contains('_')) { NewName = NewName.Split('_')[0] + "_" + Cordinates+".png"; } else { NewName = NewName + "_" + Cordinates+".png"; } fInfo.MoveTo(Server.MapPath("/Notes/" + NewName)); return NewName+"æ"+Path.GetFileNameWithoutExtension(Name); } public string PostMessage(string Note, string color,string ConnectionID) { Bitmap bmp = new Bitmap(Server.MapPath("/papers/" + color + ".png")); RectangleF rectf; if (color != "yellow") rectf = new RectangleF(40, 40, 200, 300); else rectf = new RectangleF(50, 60, 300, 300); Graphics g = Graphics.FromImage(bmp); g.SmoothingMode = SmoothingMode.AntiAlias; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.PixelOffsetMode = PixelOffsetMode.HighQuality; if (color == "red") g.DrawString(Note, new Font("Comic Sans MS", 18, FontStyle.Bold), Brushes.White, rectf); else if (color == "yellow") g.DrawString(Note, new Font("Comic Sans MS", 31, FontStyle.Bold), Brushes.Red, rectf); else if (color == "green") g.DrawString(Note, new Font("Comic Sans MS", 35, FontStyle.Bold), Brushes.Blue, rectf); else if (color == "blue") g.DrawString(Note, new Font("Comic Sans MS", 18, FontStyle.Bold), Brushes.Black, rectf); g.Flush(); Guid imgName = Guid.NewGuid(); bmp.Save(Server.MapPath("/notes/" + imgName + ".png")); return imgName.ToString(); } } } |
Index.cshtml(Full):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
@{ Layout = null; } <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width" /> <title>Index</title> <script src="~/Scripts/jquery-2.1.4.min.js"></script> <script src="~/Scripts/jquery-ui-1.11.4.min.js"></script> <script> function init() { $(".paper").draggable({ start: function () { //coordinates(this); }, stop: function () { var _left = $(this)[0].style.left.replace("px", ""); var _top = $(this)[0].style.top.replace("px", ""); var left = _left; var top = _top; coordinates(top, left, this.src); } }); $(".paper").dblclick(function () { $.post("/Home/DeleteImage", { imgUrl: this.src, ConnectionID: connectionID }).done(function (imgName) { var object = $('img[src*="' + imgName + '"]'); object[0].remove(); }); }); } function AddNote(id) { switch (id) { case 1: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'red' }).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } case 2: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'yellow' }).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } case 3: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'blue'}).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } case 4: { $.post("/Home/PostMessage", { Note: $('#txtNote').val(), color: 'green'}).done(function (imgName) { $('#draggable').append("<img src='/Notes/" + imgName + ".png' class='paper' style='position:absolute'/>"); init(); }); break; } } $("#txtNote").val(""); $("#txtNote").focus(); } $(document).ready(function () { $('#txtNote').focus(function () { if ($('#txtNote').val().trim() == 'Yazmak İstediğiniz Notu Belirtiniz!') { $('#txtNote').val(''); } }).blur(function () { if ($('#txtNote').val().trim() == '') { $('#txtNote').val('Yazmak İstediğiniz Notu Belirtiniz!') } }); $.ajax({ url: '/Home/GetImages', type: 'post', dataType: 'json', success: function (imageList) { for (var i = 0; i < imageList.length; i++) { if (imageList[i].ImageName.split('_').length > 1) { var _top = imageList[i].ImageName.split('_')[1].split('x')[0]; var _left = imageList[i].ImageName.split('_')[1].split('x')[1].replace('.png', ''); $('#draggable').append("<img src='/Notes/" + imageList[i].ImageName + "' class='paper' style='top:" + _top + "px; left: " + _left + "px; position:absolute'/>"); } else { $('#draggable').append("<img src='/Notes/" + imageList[i].ImageName + "' class='paper' style='position:absolute' />"); } }; init(); } }); }); var coordinates = function (_top, _left, src) { var name = src; console.log(src); var top = _top; var left = _left; var connectionID = 0; console.log("top:" + top + " left:" + left); $.post("/Home/ChangeImageName", { Name: name, Cordinates: top + "x" + left, ConnectionID: connectionID }).done(function (newSrc) { var _newSrc = newSrc.split('æ')[0]; var _name = newSrc.split('æ')[1]; var object = $('img[src*="' + _name + '"]'); object[0].src = "http://localhost:34544/Notes/" + _newSrc; }); } </script> <style> img.paper { width: 150px; height: 150px; padding: 0.5em; } img.menu { width: 50px; height: 50px; padding: 0.5em; } </style> </head> <body> <div id="container"> <div id="menu" style="background-image: url('/Menu/Background2.png');height:70px; z-index:999999"> <img src="~/Menu/MenuRed.png" class="menu" onclick="AddNote(1)" /> <img src="~/Menu/MenuYellow.png" class="menu" onclick="AddNote(2)" /> <img src="~/Menu/MenuBlue.png" class="menu" onclick="AddNote(3)" /> <img src="~/Menu/MenuGreen.png" class="menu" onclick="AddNote(4)" /> <textarea rows="3" cols="30" id="txtNote" style="font-size:medium; color:cornflowerblue;font-family:'Times New Roman';">Yazmak İstediğiniz Notu Belirtiniz!</textarea> </div> <br /> <div id="draggable"> @*<img src="/Papers/yellow.png" class="paper"/> <img src="/Papers/green.png" class="paper" /> <img src="/Papers/blue.png" class="paper" /> <img src="/Papers/red.png" class="paper" />*@ </div> </div> <script> init(); </script> </body> </html> |
Source:
- https://stackoverflow.com/questions/6826921/write-text-on-an-image-in-c-sharp
- https://stackoverflow.com/questions/6311545/c-sharp-write-text-on-bitmap/6311628
- https://stackoverflow.com/questions/21431879/jquery-drag-to-get-start-and-stop-coordinates
- https://stackoverflow.com/questions/849030/how-do-i-get-the-coordinate-position-after-using-jquery-drag-and-drop
Yine güzel bir makale olmuş, ellerinize sağlık devamını bekliyoruz, özellikle SignalR üzerine.
Teşekkürler Mustafa;
En kısa zaman da devamı gelicek. Kodlar hazır da, makalesi kaldı:)