1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Net; 5 using System.Windows; 6 using System.Windows.Controls; 7 using System.Windows.Documents; 8 using System.Windows.Input; 9 using System.Windows.Media; 10 using System.Windows.Media.Animation; 11 using System.Windows.Shapes; 12 13 using System.Windows.Threading; //因为要用到DispatcherTimer等 14 using System.Windows.Media.Imaging; //因为要用到BitmapImage 15 using System.Diagnostics; //因为要用到Debug 16 17 namespace 图片轮盘转动 18 { 19 public partial class MainPage : UserControl 20 { 21 22 #region 定义变量 23 private Boolean page_loaded = false; 24 List<object> angleValues = new List<object>(); //转盘图片在转盘中的角度位置 25 26 private int num_images = 20; //当前图片数量,初始化成20 27 28 private int radiusX = 500; //设置椭圆的长半径 29 private int radiusY = 110; //设置椭圆的短半径 30 31 private int centerX = 460; //设置椭圆的X坐标 32 private int centerY = 260; //设置椭圆的Y坐标 33 34 private double speed = 0; 35 private DispatcherTimer myTimer; 36 37 private bool main_down = false; 38 39 private DispatcherTimer autoTimer = new DispatcherTimer(); 40 #endregion 41 42 public MainPage() 43 { 44 InitializeComponent(); 45 46 ResetImagesButton.Click += new RoutedEventHandler(ResetImagesButton_Click); //按下Reset按钮时做ResetImagesButton_Click操作 47 48 myTimer = new DispatcherTimer(); 49 myTimer.Interval = TimeSpan.FromMilliseconds(33); 50 myTimer.Tick += new EventHandler(myTimer_Tick); 51 52 //Console.WriteLine("call start"); 53 54 //设置数量控制滑条的最大值与最小值 55 numPhotosSlider.Maximum = 180; 56 numPhotosSlider.Minimum = 10; 57 58 //设置X半径控制滑条的最大值与最小值 59 radiusSliderX.Maximum = 500; 60 radiusSliderX.Minimum = 320; 61 62 //设置Y半径控制滑条的最大值与最小值 63 radiusSliderY.Maximum = 200; 64 radiusSliderY.Minimum = 100; 65 66 Loaded += new RoutedEventHandler(Page_Loaded); 67 68 BuildImages(); 69 } 70 71 72 #region 定义要调用的函数 73 74 #region Page_Load事件 75 void Page_Loaded(object sender, RoutedEventArgs e) 76 { 77 78 myTimer.Start(); 79 80 //加载默认初始照片 81 Uri uri = new Uri("images/1.jpg", UriKind.Relative); 82 ImageSource imgSource = new BitmapImage(uri); 83 mainImage.Source = imgSource; 84 mainImageReflection.Source = imgSource; 85 86 //Debug.WriteLine("Loaded: " + mainImage.Source); 87 page_loaded = true; //设置page_loaded标志,表明已经加载了图片了 88 89 } 90 91 #endregion 92 93 #region Canvas_MouseLeftButtonDown事件 94 void Canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 95 { 96 Canvas c = sender as Canvas; 97 98 //c.Opacity = 0.5; 99 100 Rectangle r = c.Children[0] as Rectangle; //取得边框 101 Image img = c.Children[1] as Image; //取得图片 102 img.Opacity = 0.3; //设置图片透明度 103 104 //Debug.WriteLine("canvas down"); 105 106 //加载点击选中的图片 107 mainImage.Source = img.Source; 108 mainImageReflection.Source = img.Source; 109 //设置边框颜色 110 r.Stroke = new SolidColorBrush(Colors.Red); 111 } 112 113 #endregion 114 115 #region 清除所有图片+RemoveImages 116 void RemoveImages() 117 { 118 angleValues = new List<object>(); //重新new一个angleValues 119 120 for (int i = 0; i < num_images; i++) //移除所有图片 121 { 122 Canvas c = this.FindName("imageHolder_" + i) as Canvas; 123 if (c != null) 124 { 125 root.Children.Remove(c); 126 } 127 } 128 129 } 130 #endregion 131 132 #region 加载指定数量的图片+BuildImages 133 private void BuildImages() 134 { 135 int cnt = 1; //计数 136 137 for (int i = 0; i < num_images; i++) 138 { 139 #region 放置图片的Canvas创建与设置 140 Canvas c = new Canvas(); 141 142 c.Name = "imageHolder_" + i; 143 c.Width = 100; 144 c.Height = 100; 145 146 //Microsoft.Surface.Presentation.Contacts.AddPreviewContactDownHandler(c, CanvasImage_PreviewContactDown); 147 148 c.MouseLeftButtonDown += new MouseButtonEventHandler(Canvas_MouseLeftButtonDown); //加载鼠标点击事件 149 150 #endregion 151 152 #region 图片的边框创建与设置 153 154 #region 创建一个边框 155 Rectangle r = new Rectangle(); 156 r.Width = 100; 157 r.Height = 100; 158 #endregion 159 160 #region 边框填充方法一:直接填充图片所在的边框 161 // r.Fill = new SolidColorBrush(Colors.Orange); 162 #endregion 163 164 #region 边框填充方法二:手工创建一个Brush,并使用此Brush来填充图片所在的边框 165 //创建一个Brush 166 LinearGradientBrush myLGB = new LinearGradientBrush(); 167 myLGB.StartPoint = new Point(0, 0); 168 myLGB.EndPoint = new Point(0, 1); 169 170 GradientStop gs1 = new GradientStop(); 171 gs1.Color = Colors.White; 172 gs1.Offset = 0.0; 173 174 GradientStop gs2 = new GradientStop(); 175 gs2.Color = Colors.Gray; 176 gs2.Offset = 1.0; 177 178 179 myLGB.GradientStops.Add(gs1); 180 myLGB.GradientStops.Add(gs2); 181 182 //使用上面创建的Brush来填充图片所在的边框 183 r.Fill = myLGB; 184 #endregion 185 186 r.Stroke = new SolidColorBrush(Colors.Gray); 187 188 #endregion 189 190 #region 图片控件创建与设置 191 192 //创建一个图片控件 193 Image img = new Image(); 194 img.Stretch = Stretch.Fill; 195 img.Width = 80; 196 img.Height = 80; 197 img.SetValue(Canvas.LeftProperty, 10.0); 198 img.SetValue(Canvas.TopProperty, 10.0); 199 200 201 //创建一个图片源对象 202 Uri uri = new Uri("./images/" + cnt + ".jpg", UriKind.Relative); 203 ImageSource imgSource = new BitmapImage(uri); 204 205 //如果图片小于20张,则重复使用 206 if (cnt < 20) 207 { 208 cnt++; 209 } 210 else 211 { 212 cnt = 1; 213 } 214 215 img.Source = imgSource; 216 217 #endregion 218 219 #region 在上面创建的Canvas中添加创建的边框和图片控件 220 c.Children.Add(r); 221 c.Children.Add(img); 222 #endregion 223 224 #region 设置图片缩放比例 225 ScaleTransform st = new ScaleTransform(); 226 st.CenterX = 50; 227 st.CenterY = 50; 228 st.ScaleX = 1; 229 st.ScaleY = 1; 230 231 c.RenderTransform = st; 232 #endregion 233 234 #region 图片角度位置的计算与保存 235 double ang = (double)i * ((Math.PI * 2) / num_images); //取得对应位置的角度值 236 angleValues.Add(ang); //把角度值保存到List中 237 #endregion 238 239 #region 把上面创建的Canvas添加到页面上 240 // c.SetValue(Canvas.LeftProperty, i * 100.0); 241 root.Children.Add(c); 242 #endregion 243 } 244 245 PositionImagesInCircle(); //放置对应的图片 246 } 247 248 249 #endregion 250 251 #region 设置各个转盘图片在转盘中的位置以及缩放比例+PositionImagesInCircle 252 private void PositionImagesInCircle() 253 { 254 for (int i = 0; i < num_images; i++) //遍历所有指定数量的图片 255 { 256 //根据角度确定椭圆轨迹上的坐标值 257 double my_x = (double)Math.Cos((double)angleValues[i]) * radiusX + centerX; //取得X轴坐标值 258 double my_y = (double)Math.Sin((double)angleValues[i]) * radiusY + centerY; //取得Y轴坐标值 259 260 Canvas c = root.FindName("imageHolder_" + i) as Canvas; //找到子图片所在Canvas 261 c.SetValue(Canvas.LeftProperty, my_x); //设置Canvas的坐标值 262 c.SetValue(Canvas.TopProperty, my_y); 263 c.SetValue(Canvas.ZIndexProperty, (int)my_y); //设置Canvas的显示层次值,在Y坐标上值大图片的覆盖值小的图片 264 265 //缩放变换ScaleTransform允许我们对元素进行缩放,通过属性ScaleX和ScaleY来分别指定在X轴和Y轴上的缩放比例, 266 //同样也可以使用属性CenterX和CenterY来指定缩放中心 267 ScaleTransform st = c.RenderTransform as ScaleTransform; 268 269 270 double my_scale = (my_y - st.ScaleY) / (centerY + radiusY - st.ScaleY); //按一定方式进行缩放,原则是Y轴值大的图片大,Y轴值小的图片小 271 272 //double my_scale = (my_x - st.ScaleX) / (centerX + radiusX - st.ScaleX); //另外一种缩放公式 273 //double my_scale = 2 + (double)Math.Cos((double)angleValues[i] - Math.PI / 2); //另外一种缩放公式 274 275 276 st.ScaleX = my_scale; 277 st.ScaleY = my_scale; 278 279 angleValues[i] = (double)angleValues[i] + speed; 280 281 } 282 283 } 284 #endregion 285 286 #region myTimer_Tick 事件处理函数 287 void myTimer_Tick(object sender, EventArgs e) 288 { 289 if (main_down) 290 { 291 PositionImagesInCircle(); //调整图片位置与缩放比例 292 } 293 } 294 #endregion 295 296 #endregion 297 298 private void numPhotosSliderChanged(object sender, RoutedPropertyChangedEventArgs<double> e) 299 { 300 Slider s = sender as Slider; 301 302 if (page_loaded) //如果页面已经加载 303 { 304 RemoveImages(); //移除所有图片 305 306 num_images = (int)s.Value; //重新设置当前应该加载的图片数量 307 308 BuildImages(); //重新加载图片 309 } 310 } 311 312 private void ResetImagesButton_Click(object sender, RoutedEventArgs e) 313 { 314 RemoveImages(); //清除所有图片 315 316 #region 恢复变量默认初始值#region 恢复变量默认初始值 317 num_images = 20; 318 radiusX = 500; 319 radiusY = 110; 320 centerX = 460; 321 centerY = 260; 322 mainImage.SetValue(Canvas.ZIndexProperty, 169); 323 #endregion 324 325 BuildImages(); //重新加载指定数量的图片 326 327 #region 重新设置滑条默认值#region 重新设置滑条默认值 328 numPhotosSlider.Value = 40.0; 329 radiusSliderX.Value = 500; 330 radiusSliderY.Value = 1100; 331 #endregion 332 } 333 334 private void radiusSliderChangedX(object sender, RoutedPropertyChangedEventArgs<double> e) 335 { 336 Slider s = sender as Slider; 337 338 if (page_loaded) //如果页面已经成功加载则作后续处理 339 { 340 RemoveImages(); //移除所有图片 341 342 radiusX = (int)s.Value; //取得新的半径值 343 344 if (s.Value < 450) //如果新的半径值低于我们要求的上限,则作调整,否则不作变动 345 { 346 //调整mainImage控件的ZIndexProperty属性,以免它因为radius的变动被后面的图片轮挡住 347 int z = (int)mainImage.GetValue(Canvas.ZIndexProperty); 348 z += 2; 349 mainImage.SetValue(Canvas.ZIndexProperty, z); 350 } 351 else 352 { 353 mainImage.SetValue(Canvas.ZIndexProperty, 169); 354 } 355 356 BuildImages(); //重新加载图片 357 } 358 359 } 360 361 362 private void MainContactDown(object sender, MouseButtonEventArgs e) 363 { 364 Point p = e.GetPosition(this); 365 Debug.WriteLine(">>" + p.Y); 366 if (p.Y > 500 && p.Y < 650) //判断是否在指定的区域内按下了鼠标 367 { 368 main_down = true; 369 } 370 } 371 372 private void MainContactUp(object sender, MouseButtonEventArgs e) 373 { 374 main_down = false; 375 } 376 377 private void root_MouseMove(object sender, MouseEventArgs e) 378 { 379 Point p = e.GetPosition(this); 380 speed = ((p.X - 500) / 500) * 0.0755; //调整轮盘的转速 381 //Debug.WriteLine("changed: " + speed); 382 } 383 384 private void radiusSliderChangedY(object sender, RoutedPropertyChangedEventArgs<double> e) 385 { 386 Slider s = sender as Slider; 387 if (page_loaded) //如果页面已经成功加载则作后续处理 388 { 389 RemoveImages(); //移除所有图片 390 391 radiusY = (int)s.Value; //取得新的半径值 392 if (s.Value < 200) //如果新的半径值低于我们要求的上限,则作调整,否则不作变动 393 { 394 //调整mainImage控件的ZIndexProperty属性,以免它因为radius的变动被后面的图片轮挡住 395 int z = (int)mainImage.GetValue(Canvas.ZIndexProperty); 396 z += 2; 397 mainImage.SetValue(Canvas.ZIndexProperty, z); 398 } 399 else 400 { 401 mainImage.SetValue(Canvas.ZIndexProperty, 169); 402 } 403 404 BuildImages(); //重新加载图片 405 } 406 } 407 408 #region autoTimer_Tick 事件处理函数#region autoTimer_Tick 事件处理函数 409 void autoTimer_Tick(object sender, EventArgs e) 410 { 411 PositionImagesInCircle(); //调整图片位置与缩放比例 412 } 413 #endregion 414 415 private void AutoSpinButton_Click(object sender, RoutedEventArgs e) 416 { 417 autoTimer.Start(); 418 autoTimer.Interval = TimeSpan.FromMilliseconds(33); 419 autoTimer.Tick += new EventHandler(autoTimer_Tick); 420 } 421 } 422 }