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 }