www.thedatafarm.com
Julia Lerman
Exploring Silverlight's InkPresenter object

Aug 2007: Updated for Silverlight 1.0 Release Candidate
[using Safari? Read this blog post first...]

Previous Next


Next, I created some interaction with the InkPresenter by allowing the user to change the ink color. I added some buttons with  a little animation in XAML and some  javascript to achieve this.




The Code

Embedding CreateSilverlight in HTML

<div id="MySilverlightHost">
   <script type="text/javascript">
      CreateSilverlight();
   </script>
</div>

CreateSilverlight.js
(updated for RC)

function createSilverlight()

 Silverlight.createObject(
   "xaml/MyInkCanvas.xaml",
    MySilverlightHost,
    "wpfobj",
    {width:'400', height:'200', inplaceInstallPrompt:false,
      background:'lightgray', isWindowless:'false', framerate:'36', version:'1.0'},
    {onError:null, onLoad:null}, null);

MyInkCanvas.xaml

<!-- this is a lot more complex as it has some WPF stuff in it: animation, gradients, etc., it does not include the addition of the pen image -->

<Canvas xmlns=\"http://schemas.microsoft.com/client/2007\" 
        xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\" 
        Loaded=\"root_Loaded\" 
        x:Name=\"root\" 
        Width=\"800\" Height=\"400\">

  <Canvas.Resources>
    <Storyboard x:Name=\"MoveBorder\">
      <DoubleAnimation x:Name=\"MoveBorderAni\"
        Storyboard.TargetName=\"ButtonBorder\"
        Storyboard.TargetProperty=\"(Canvas.Left)\"
        Duration=\"0:0:0.3\" /> 
    </Storyboard>
    <Storyboard x:Name=\"GlowButton\"> 
        <DoubleAnimation Storyboard.TargetName=\"GlowRect\" 
        Storyboard.TargetProperty=\"Opacity\" 
        From=\"0\" To=\"1\" Duration=\"0:0:0.5\" AutoReverse=\"True\"/> 
    </Storyboard>
</Canvas.Resources>

<InkPresenter x:Name=\"inkPresenterElement\" 
              Background=\"transparent\" 
              Width=\"800\" Height=\"400\" 
              MouseLeftButtonDown=\"InkPresenterMouseDown\" 
              MouseMove=\"InkPresenterMouseMove\" 
              MouseLeftButtonUp=\"InkPresenterMouseUp\"/>

<Canvas x:Name=\"RedButton\" MouseLeftButtonDown=\"RedInk\">
   <Rectangle Stroke=\"#FF8E8E8E\" StrokeThickness=\"2\" RadiusX=\"2\"
       RadiusY=\"2\" Height=\"23\" Width=\"75\" >
     <Rectangle.Fill>
       <LinearGradientBrush StartPoint=\"0.5,2.109\" EndPoint=\"0.5,-1.109\">
               <GradientStop x:Name=\"gradientStopRed1\" Color=\"DarkRed\" Offset=\"1\"/> 
              <GradientStop x:Name=\"gradientStopRed2\" Color=\"Red\" Offset=\"0.218\"/> 
       </LinearGradientBrush> 
     </Rectangle.Fill>
   </Rectangle>
   <TextBlock Canvas.Top=\"3\" Canvas.Left=\"13\" FontSize=\"12\" Foreground=\"white\" Text=\"Red Ink\" />
</Canvas>

<Canvas x:Name=\"BlueButton\" MouseLeftButtonDown=\"BlueInk\" Canvas.Left=\"75\">
   <Rectangle Stroke=\"#FF8E8E8E\" StrokeThickness=\"2\" RadiusX=\"2\"
       RadiusY=\"2\" Height=\"23\" Width=\"75\" >
     <Rectangle.Fill > 
          <LinearGradientBrush StartPoint=\"0.5,2.109\" EndPoint=\"0.5,-1.109\"> 
              <GradientStop x:Name=\"gradientStop1\" Color=\"DarkSlateBlue\" Offset=\"1\"/> 
              <GradientStop x:Name=\"gradientStop2\" Color=\"Navy\" Offset=\"0.218\"/>
          </LinearGradientBrush> 
     </Rectangle.Fill>
   </Rectangle>
   <TextBlock Canvas.Top=\"3\" Canvas.Left=\"13\" FontSize=\"12\" Foreground=\"White\" Text=\"Blue Ink\" />
</Canvas>

<Canvas x:Name=\"BlackButton\" Canvas.Left=\"150\" MouseLeftButtonDown=\"BlackInk\">
   <Rectangle Stroke=\"#FF8E8E8E\" StrokeThickness=\"2\" RadiusX=\"2\"
      RadiusY=\"2\" Height=\"23\" Width=\"75\" >
     <Rectangle.Fill> 
         <LinearGradientBrush StartPoint=\"0.5,2.109\" EndPoint=\"0.5,-1.109\"> 
              <GradientStop x:Name=\"gradientStopBlack1\" Color=\"DarkSlateGray\" Offset=\"1\"/> 
              <GradientStop x:Name=\"gradientStopBlack2\" Color=\"Black\" Offset=\"0.218\"/>
         </LinearGradientBrush>
     </Rectangle.Fill>
   </Rectangle>
   <TextBlock Canvas.Top=\"3\" Canvas.Left=\"13\" FontSize=\"12\" Foreground=\"White\" Text=\"Black Ink\" />
</Canvas>

<Canvas x:Name=\"ButtonBorder\" Canvas.Left=\"150\">
  <Rectangle StrokeThickness=\"3\" RadiusX=\"2\" RadiusY=\"2\" Height=\"23\" Width=\"75\" >
    <Rectangle.Stroke>
       <LinearGradientBrush >
           <GradientStop Color=\"Yellow\" Offset=\"0.0\"/>
           <GradientStop Color=\"Black\" Offset=\".75\"/>
       </LinearGradientBrush>
    </Rectangle.Stroke>
  </Rectangle>
</Canvas>
</Canvas>


ink.js 

var wpf;
var inkPresenter; // Corresponds to InkPresenter element in xaml
var newStroke = null; // The Stroke variable we’ll use here in mouse handlers var currentColor=\"#FF000000\"; //black

function root_Loaded(sender, args) 
{
    wpf = document.getElementById(\"wpfobj\");
    inkPresenter = sender.findname(\"inkPresenterElement\");
}

// Capture mouse and create the stroke
function InkPresenterMouseDown(sender,args)

   inkPresenter.CaptureMouse();
   newStroke = wpf.content.createFromXaml(\'<Stroke/>\');
   newStroke.StylusPoints.AddStylusPoints(args.GetStylusPoints(inkPresenter));
   newStroke.DrawingAttributes.Color=currentColor;
   inkPresenter.Strokes.Add(newStroke);
}

// Add the new points to the Stroke we’re working with
function InkPresenterMouseMove(sender,args) 
   if (newStroke != null)
   {
      newStroke.StylusPoints.AddStylusPoints(args.GetStylusPoints(inkPresenter));
   }
}

// Release the mouse
function InkPresenterMouseUp(sender,args) 
{
   newStroke = null;
}

function RedInk(sender,args)
{
currentColor="#FFFF0000";
//also fire the storyboard trigger
borderAnimation=sender.findName("MoveBorderAni");
StartLeft=EndLeft; //position of current color button
EndLeft=0; //postion of red button
borderAnimation.from=StartLeft;
borderAnimation.to=EndLeft;
sender.findName("MoveBorder").begin();
}

function BlueInk(sender,args)
{
currentColor="#FF000080";
//also fire the storyboard trigger
borderAnimation=sender.findName("MoveBorderAni");
StartLeft=EndLeft; //position of current color button
EndLeft=75; //postion of navy button
borderAnimation.from=StartLeft;
borderAnimation.to=EndLeft;
sender.findName("MoveBorder").begin();
}

function BlackInk(sender,args)
{
currentColor="#FF000000";
borderAnimation=sender.findName("MoveBorderAni");
StartLeft=EndLeft; //position of current  button
EndLeft=150; //postion of black button
borderAnimation.from=StartLeft;
borderAnimation.to=EndLeft;
sender.findName("MoveBorder").begin();
}