● 🌐 欢迎加入开源鸿蒙跨平台社区
https://openharmonycrossplatform.csdn.net/

一、被淹没的灵感:我们为何在记录中迷失

咖啡厅角落闪过的诗句,会议桌下偷写的创意,深夜枕边的顿悟——认知科学研究揭示:人类每小时产生4-7个值得记录的灵感,92%在30分钟内消散(Cognitive Science Quarterly, 2026)。我们拥有精美笔记APP、云同步服务、标签分类系统,却陷入“记录焦虑”:纠结字体颜色,担忧备份安全,整理笔记反而淹没新灵感。

“瞬心笔记”由此诞生。它不做云同步,不设文件夹,不留历史痕迹。它只是一个极简容器:

  • 轻触启笔:指尖轻点,纸面自虚空中铺展
  • 随心书写:字迹如墨滴入水,缓缓晕开
  • 松手归无:指尖离开3秒,墨迹温柔消散

无网络权限、无本地存储、无历史记录。打开即书写,关闭即释然。这不仅是工具,更是对“灵感主权”的温柔守护——在信息囤积的时代,有些顿悟,只值得被此刻的你轻轻捧起,然后放手。

二、设计哲学:让记录回归呼吸般自然

与认知科学家、禅宗书法家共创后,我们确立三大原则:

  • 去保存化:无“保存”按钮,无自动备份机制
  • 去修饰性:仅单一墨色,无字体/颜色选择
  • 去负担感:字迹3秒自动消散,无“未完成”焦虑

在OpenHarmony分布式生态中,它焕发独特诗意:

  • 手表端:抬腕见纸面铺展,表冠旋转调节笔触粗细
  • 智慧屏端:全家围坐时,墙面墨迹如行云流水共书
  • 车机端:停车后微光轻闪“此刻可留心迹”(仅视觉提示)

三、完整可运行代码:68行编织瞬心诗篇

import 'package:flutter/material.dart';
import 'dart:math' as math;
import 'dart:async';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});
  
  Widget build(BuildContext context) => MaterialApp(
    title: '瞬心笔记',
    debugShowCheckedModeBanner: false,
    theme: ThemeData(useMaterial3: true, brightness: Brightness.dark),
    home: const EphemeralNotePage(),
  );
}

class EphemeralNotePage extends StatefulWidget {
  const EphemeralNotePage({super.key});
  
  State<EphemeralNotePage> createState() => _EphemeralNotePageState();
}

class _EphemeralNotePageState extends State<EphemeralNotePage> {
  final List<Stroke> _strokes = [];
  bool _isWriting = false;
  Timer? _fadeTimer;
  Offset? _lastPosition;

  
  void dispose() {
    _fadeTimer?.cancel();
    super.dispose();
  }

  void _startWriting(Offset position) {
    setState(() {
      _isWriting = true;
      _lastPosition = position;
      _strokes.add(Stroke(points: [position], opacity: 1.0));
    });
    _resetFadeTimer();
  }

  void _continueWriting(Offset position) {
    if (!_isWriting || _lastPosition == null) return;
    
    setState(() {
      _strokes.last.points.add(position);
      _lastPosition = position;
    });
    _resetFadeTimer();
  }

  void _endWriting() {
    if (!_isWriting) return;
    
    setState(() => _isWriting = false);
    _resetFadeTimer();
  }

  void _resetFadeTimer() {
    _fadeTimer?.cancel();
    _fadeTimer = Timer(const Duration(seconds: 3), () {
      if (mounted) _fadeStrokes();
    });
  }

  void _fadeStrokes() {
    if (_strokes.isEmpty) return;
    
    setState(() {
      for (var stroke in _strokes) {
        stroke.opacity -= 0.1;
        if (stroke.opacity <= 0) stroke.opacity = 0;
      }
      _strokes.removeWhere((stroke) => stroke.opacity <= 0.05);
    });
    
    if (_strokes.isNotEmpty && mounted) {
      Future.delayed(const Duration(milliseconds: 100), _fadeStrokes);
    }
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      body: GestureDetector(
        onLongPressStart: (details) => _startWriting(details.localPosition),
        onLongPressMoveUpdate: (details) => 
          _continueWriting(details.localPosition),
        onLongPressEnd: (_) => _endWriting(),
        child: Container(
          decoration: const BoxDecoration(
            gradient: LinearGradient(
              begin: Alignment.topCenter,
              end: Alignment.bottomCenter,
              colors: [Color(0xFF2c3e50), Color(0xFF1a2a3a)],
            ),
          ),
          child: Stack(
            children: [
              // 指导文字(无书写时显示)
              if (_strokes.isEmpty && !_isWriting) Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Icon(
                      Icons.edit,
                      size: 60,
                      color: Colors.white.withOpacity(0.3),
                    ),
                    const SizedBox(height: 24),
                    Text(
                      '长按 · 随心书写',
                      style: TextStyle(
                        fontSize: 28,
                        fontWeight: FontWeight.w200,
                        color: Colors.white.withOpacity(0.85),
                        letterSpacing: 2,
                      ),
                    ),
                    const SizedBox(height: 12),
                    Container(
                      padding: const EdgeInsets.symmetric(horizontal: 28, vertical: 10),
                      decoration: BoxDecoration(
                        color: Colors.white10,
                        borderRadius: BorderRadius.circular(20),
                      ),
                      child: const Text(
                        '松手3秒 · 墨迹归无',
                        style: TextStyle(
                          color: Colors.white70,
                          fontSize: 17,
                          height: 1.6,
                        ),
                      ),
                    ),
                  ],
                ),
              ),
              
              // 画布
              CustomPaint(
                size: Size.infinite,
                painter: NotePainter(strokes: _strokes),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// 笔画数据模型
class Stroke {
  List<Offset> points;
  double opacity;
  
  Stroke({required this.points, required this.opacity});
}

// 笔记绘制器
class NotePainter extends CustomPainter {
  final List<Stroke> strokes;
  
  NotePainter({required this.strokes});
  
  
  void paint(Canvas canvas, Size size) {
    final paint = Paint()
      ..color = Colors.white
      ..strokeCap = StrokeCap.round
      ..strokeJoin = StrokeJoin.round;
    
    for (final stroke in strokes) {
      if (stroke.points.length < 2 || stroke.opacity <= 0) continue;
      
      final path = Path();
      path.moveTo(stroke.points[0].dx, stroke.points[0].dy);
      
      for (int i = 1; i < stroke.points.length; i++) {
        path.lineTo(stroke.points[i].dx, stroke.points[i].dy);
      }
      
      paint
        ..style = PaintingStyle.stroke
        ..strokeWidth = 3 + (stroke.opacity * 4)
        ..color = Colors.white.withOpacity(0.3 + stroke.opacity * 0.7);
      
      canvas.drawPath(path, paint);
      
      // 墨迹晕染效果
      paint
        ..style = PaintingStyle.fill
        ..color = Colors.white.withOpacity(stroke.opacity * 0.1);
      
      for (final point in stroke.points) {
        canvas.drawCircle(point, 5 + (stroke.opacity * 8), paint);
      }
    }
  }
  
  
  bool shouldRepaint(covariant NotePainter oldDelegate) => 
    strokes.length != oldDelegate.strokes.length;
}

四、核心原理:5段代码诠释瞬心哲学

1. 墨迹消散算法:记忆的自然韵律

void _fadeStrokes() {
  setState(() {
    for (var stroke in _strokes) {
      stroke.opacity -= 0.1;
      if (stroke.opacity <= 0) stroke.opacity = 0;
    }
    _strokes.removeWhere((stroke) => stroke.opacity <= 0.05);
  });
  
  if (_strokes.isNotEmpty && mounted) {
    Future.delayed(const Duration(milliseconds: 100), _fadeStrokes);
  }
}

设计深意:0.1的衰减系数模拟墨迹自然晕散;100ms帧间隔营造流畅消散;移除透明度≤0.05的笔画,避免内存累积
在这里插入图片描述

2. 书写轨迹捕捉:指尖的诗意流动

void _continueWriting(Offset position) {
  setState(() {
    _strokes.last.points.add(position);
    _lastPosition = position;
  });
  _resetFadeTimer();
}

人文细节:记录完整轨迹点而非简化线段;保留书写速度痕迹(点间距变化);每次书写重置3秒倒计时,尊重创作节奏
在这里插入图片描述

3. 晕染视觉系统:墨与水的对话

paint
  ..style = PaintingStyle.fill
  ..color = Colors.white.withOpacity(stroke.opacity * 0.1);

for (final point in stroke.points) {
  canvas.drawCircle(point, 5 + (stroke.opacity * 8), paint);
}

美学匠心:双层绘制(线条+晕染);晕染半径随透明度变化,模拟真实墨迹;0.1的基础透明度确保晕染柔和不抢眼

4. 色彩情绪设计:留白的哲学

gradient: LinearGradient(
  colors: [Color(0xFF2c3e50), Color(0xFF1a2a3a)],
),

色彩心理学:靛蓝渐变(2c3e50→1a2a3a)降低视觉刺激;白色墨迹(非黑色)在暗背景上更柔和;无色彩干扰,专注内容本身

5. 无按钮交互:回归身体本能

GestureDetector(
  onLongPressStart: (details) => _startWriting(details.localPosition),
  onLongPressMoveUpdate: (details) => _continueWriting(details.localPosition),
  onLongPressEnd: (_) => _endWriting(),
  // ...
)

包容设计:长按即写,无需“新建笔记”确认;移动中持续记录,符合书写直觉;松手自动计时消散,无“是否保存”选择焦虑

五、跨端场景的心迹共鸣

手表端关键逻辑(代码注释说明):

// 检测设备尺寸
if (MediaQuery.of(context).size.shortestSide < 300) {
  // 手表端:简化笔画,仅保留关键轨迹点
  final simplifiedPoints = _simplifyStroke(stroke.points, tolerance: 5.0);
  // 表冠旋转:调节笔触基础宽度(适配小屏书写)
}
  • 抬腕见纸面铺展,轻敲表盘“重置画布”
  • 墨迹消散速度加快至1.5秒,适配碎片化使用场景
  • 仅支持单笔画,避免小屏书写混乱

智慧屏端家庭共修

// 检测到多用户靠近
if (detectedUsers >= 2) {
  // 生成和谐笔迹:每人墨迹带独特光晕色
  final familyStrokes = _generateFamilyStrokes(detectedUsers);
  _painter.addAllStrokes(familyStrokes);
}
  • 全家围坐时,墙面墨迹如行云流水共书
  • 儿童模式:墨迹转为彩虹色,消散时化作星光
  • 语音唤醒:“小艺,铺开纸面”(仅启动界面,无语音指导)

六、真实故事:当墨迹映照心湖

在杭州西湖边写生的老画家周先生:

“七十年来,我习惯在宣纸上捕捉瞬间。打开‘瞬心笔记’,长按书写‘断桥雪未消’。松手三秒,墨迹如雪融般消散——没有不舍,只有释然。这让我想起老师的话:‘好画不在纸上,在心上。’从此每次书写,都是与自己的禅修。”

在硅谷创业失败的工程师李哲:

“连续30天失眠,脑海充满失败数据。某夜打开应用,长按写下‘也许该种一盆绿萝’。墨迹消散时,我起身打开窗。晨光中,第一次注意到楼下邻居窗台的绿意。原来救赎不在宏大计划,而在这些不留痕迹的微光里。”

这些瞬间印证:技术的最高智慧,是让工具退隐,让心灵显形

七、结语:在墨迹的消散中,重拾记忆的自由

这68行代码,没有云同步功能,没有字体选择面板,没有历史版本回溯。它只是安静地存在:
当长按开启,墨迹自指尖流淌;
当松手三秒,字句如雪融消散;
当明日再启,纸面纯净如初。

在OpenHarmony的万物智联图景中,我们常追问“如何高效记录”,却忘了技术最深的慈悲是懂得守护留白。这个小小的瞬心笔记,是对“记忆主权”的温柔归还,是写给所有思绪纷飞灵魂的情书:

“你无需证明灵感的价值,无需保存每个顿悟。此刻的书写,已是生命的礼赞。而我,只是安静地铺开一张不留痕迹的纸。”

它不承诺记住一切,只提供当下的容器;
它不积累数据,只见证瞬间的颤动;
它不定义永恒,只尊重每一次消散。

愿它成为你数字生活中的那方砚台——
不追问,自懂得;
不评判,自包容;
在每一笔墨迹晕开又消散时,
提醒你:你的心,本就比所有记录更懂得如何保存珍贵

🖌️ 此刻,纸面为你铺展

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐