我需要与下图进行交互。我想添加两个滑块来更改下图中红点的(x,y)位置。虚线和圆圈也应随着红点的作用而改变,而蓝点应停留在此。
我在matplotlib下找到了一些滑块的演示,而所有这些演示都更新了该图的曲线。我的数字比他们复杂一点,我不知道如何更新其中的一部分。
import numpy as np
from matplotlib.lines import Line2D
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import rcParams
from matplotlib.widgets import Slider
fig, ax = plt.subplots()
ax.axis([-5,15,-5,15])
ax.set_aspect(1) # x y轴等比例显示
anchorNum = 4
anchorX = [0,10,0,10]
anchorY = [0,0,10,10]
anchorName = ['A0', 'A1', 'A2', 'A3']
colorArray = ['blue', 'green', 'magenta', 'green']
ax.scatter(anchorX, anchorY, s=200) # plot stable blue point
for i, txt in enumerate(anchorName):
ax.annotate(txt, (anchorX[i], anchorY[i]), fontsize = 20)
initTagX = np.random.random_sample()*10
initTagY = np.random.random_sample()*10
tagPos = [initTagX, initTagY]
ax.scatter(tagPos[0], tagPos[1], c='red', s=300) # plot the red point
# plot the dash line
for i in range(anchorNum):
anchorPos = (anchorX[i], anchorY[i])
diffVector = [(tagPos[0] - anchorX[i]), (tagPos[1] - anchorY[i])]
dist = np.linalg.norm(diffVector,ord = 2) # 计算二阶范数 平方和开根号
circle = plt.Circle(anchorPos, dist, color = colorArray[i], fill = False, linestyle='--', linewidth=4)
ax.add_artist(circle)
ax.plot([anchorX[i], tagPos[0]], [anchorY[i], tagPos[1]], linestyle = '--', color = colorArray[i], linewidth=4)
plt.show()
答案 0 :(得分:1)
您的图和可能看到的示例之间的唯一区别是,在更改滑块时,您需要一次更新几项内容。
更改x或y位置时,需要更新红点的x或y位置,4个圆的半径以及4条虚线的位置。
下面的代码可以完成所有操作。移动滑块时,将调用update_rp_x
或update_rp_y
。依次使用更新的坐标调用函数update_plot
,然后移动所有相关的绘图要素。对于红点,我从使用ax.scatter
切换到ax.plot
,因为更新位置(例如rp.set_xdata()
稍微更简单)。线和圆在第一次绘制时存储在列表中,因此当我们对其进行更新时,我们可以循环遍历这些列表并依次更新每个列表。圆只需要更改其半径(我们可以使用Circle.set_radius
来更改半径,然后再次更改包含set_xdata
和set_ydata
的线。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider
fig, ax = plt.subplots()
ax.axis([-5,15,-5,15])
ax.set_aspect(1) # x y
# Make room at the bottom for sliders
fig.subplots_adjust(bottom=0.3)
# Initial tag location
initTagX = np.random.random_sample()*10
initTagY = np.random.random_sample()*10
tagPos = [initTagX, initTagY]
# Set up the anchors
anchorNum = 4
anchorX = [0,10,0,10]
anchorY = [0,0,10,10]
anchorName = ['A0', 'A1', 'A2', 'A3']
colorArray = ['blue', 'green', 'magenta', 'green']
# Plot the anchors
ax.scatter(anchorX, anchorY, s=100) # plot stable blue point
# Label the anchors
for i, txt in enumerate(anchorName):
ax.annotate(txt, (anchorX[i], anchorY[i]), fontsize = 10)
# Plot initial location of red point
rp, = ax.plot(tagPos[0], tagPos[1], c='red', marker='o', ms=10) # plot the red point
# Store circles and lines for update later
circles = []
lines = []
# Plot initial circles
for i in range(anchorNum):
anchorPos = (anchorX[i], anchorY[i])
diffVector = [(tagPos[0] - anchorX[i]), (tagPos[1] - anchorY[i])]
dist = np.linalg.norm(diffVector,ord = 2)
circle = plt.Circle(anchorPos, dist, color = colorArray[i], fill = False, linestyle='--', linewidth=2)
circles.append(ax.add_artist(circle))
lines.append(ax.plot([anchorX[i], tagPos[0]], [anchorY[i], tagPos[1]], linestyle = '--',
color = colorArray[i], linewidth=2)[0])
def update_plot(xpos, ypos):
'''
This function updates the radius of the circles
and the position of the dashed lines
'''
# Update the tag position
tagPos = [xpos, ypos]
rp.set_xdata(xpos)
rp.set_ydata(ypos)
for i in range(anchorNum):
anchorPos = (anchorX[i], anchorY[i])
diffVector = [(tagPos[0] - anchorX[i]), (tagPos[1] - anchorY[i])]
dist = np.linalg.norm(diffVector,ord = 2)
# Now we actually update the circles and dashed lines
circles[i].set_radius(dist)
lines[i].set_xdata([anchorX[i], tagPos[0]])
lines[i].set_ydata([anchorY[i], tagPos[1]])
return tagPos
def update_rp_x(xpos):
''' This function updates the x position of the red point '''
global tagPos
tagPos = update_plot(xpos, tagPos[1])
fig.canvas.draw_idle()
def update_rp_y(ypos):
''' This function updates the y position of the red point '''
global tagPos
tagPos = update_plot(tagPos[0], ypos)
fig.canvas.draw_idle()
# Create Axes for the sliders
axcolor = '#909090'
sax_x = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
sax_y = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)
# Create sliders
sx = Slider(sax_x, 'x position', -5, 15, valinit=initTagX)
sy = Slider(sax_y, 'y position', -5, 15, valinit=initTagY)
# Tell sliders which function to call when changed
sx.on_changed(update_rp_x)
sy.on_changed(update_rp_y)
plt.show()